假设B复制了A 此时 B 和 A 的值相同, 但是当修改 A 的值,如果 B 的值随着 A 的值变化而变化 则说明是浅拷贝;如果 B 的值不随着 A 的变化而变化,则说明是深拷贝

浅拷贝

简单的赋值 => 其实复制的是a的引用地址,而并非堆里面的值

  let a = [0,1,2,3,4,5]
  let b = a
  console.log(a===b) //true
  a[0]=1
  console.log(a,b) //(6) [1, 1, 2, 3, 4, 5] (6) [1, 1, 2, 3, 4, 5]

当 b = a 赋值时,实际上是把 a 的引用地址赋给了 b ,而不是简单的值

将 a 比喻成是一个办公室 a 的内容是办公室里的每个人,内存比作整个办公室,a的引用地址就是每个人配套的办公桌。 当 b = a 时 实际上是将a的引用地址复制了过来 也就相当于将每个人及其办公桌复制过来了,当办公室有人员变动时,a的办公桌上的人由A 变成A1,由于b复制的是引用地址,所以b也从A变成了A1

深拷贝

一般需要递归实现 => 深拷贝,是拷贝对象各个层级的属性

    function deepClone(obj){
      let objClone = Array.isArray(obj)?[]:{}
      if(obj && typeof obj === 'object'){
        for(key in obj){
          if(obj.hasOwnProperty(key)){
            //判断obj子元素是否为对象,如果是,递归复制
            if(obj[key] && typeof obj[key] === 'object'){
              objClone[key] = deepClone(obj[key])
            }else{
              //如果不是 简单复制
              objClone[key] = obj[key]
            }
          }
        }
      }
      return objClone
    }
    let a = [1,2,3,4]
    let b = deepClone(a)
    a[0] = 9
    console.log(a,b) // (4) [9, 2, 3, 4] (4) [1, 2, 3, 4]

ps: arr.slice() 方法和 arr.concat() 虽然看起来像深拷贝 但是不是深拷贝

  let a=[0,1,[2,3],4],
  b=a.slice();
  console.log(a,b) // (4)[0,1,[2,3],4]  (4)[0,1,[2,3],4]
  a[0]=1; 
  console.log(a,b) // (4)[1,1,[2,3],4]  (4)[0,1,[2,3],4]
  a[2][0]=1;
  console.log(a,b) // (4)[1,1,[1,3],4]  (4)[0,1,[1,3],4] 
  //b对象的一级属性确实不受影响了,但是二级属性还是没能拷贝成功,仍然脱离不了a的控制,说明slice根本不是真正的深拷贝。
  //第一层的属性确实深拷贝,拥有了独立的内存,但更深的属性却仍然公用了地址,所以才会造成上面的问题

除了递归还可以使用JSON对象的parse和stringify

  function deepClone(obj){
    let _obj = JSON.stringify(obj)
    let objClone = JSON.parse(_obj)
    return objClone
  }
  let a = [1,2,3,4]
  let b = deepClone(a)
  a[0] = 9
  console.log(a,b) // (4) [9, 2, 3, 4] (4) [1, 2, 3, 4]