浅拷贝与深拷贝

深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

 

浅拷贝(shallowCopy)

  • 只是增加了一个指针指向已存在的内存地址

深拷贝(deepCopy)

  1. 是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存

浅拷贝:

  1. Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象(注意:当object只有一层的时候,是深拷贝)
  2. 使用扩展运算符(…)来解决
  3. Array.prototype.concat()

  4. Array.prototype.slice()

深拷贝的方式:

  1. 使用JSON对象的stringify和parse方法
    • 数组和对象深拷贝都可用
    • 缺点:  循环obj 中的每一项,如果里面还有复杂数据类型,则不可用
  2. 使用递归 (对象,数组可用)

    1. 判断拷贝对象是数组还是函数   Array.isArray(obj) ? [] : {};
    2. 判断拷贝对象非空并且是 typeof (obj) === "object" (对象和数组的  typeof 都是object)
    3. let in 遍历拷贝对象
    4. 如果拷贝对象里面的属性是对象或数组,递归调用方法,对每一项深度遍历
    5. 如果不是,则直接复制赋值
  3. es6的对象/数组解构
  4. 使用数组的slice()
  5. 使用数组的 concat() 方法

实现

<script>
    // 深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存
    // _tmp和result是相互独立的,没有任何联系,有各自的存储空间。

    // 1.使用JSON对象的stringify和parse方法
    //  数组和对象深拷贝都可用
    // 缺点 循环obj 中的每一项,如果里面还有复杂数据类型,则不可用
    let deepClone = function (obj) {
      let _tmp = JSON.stringify(obj);//将js对象转为json字符串形式
      let result = JSON.parse(_tmp);//将json字符串转为原生js对象
      return result;
    }

    // 2. es6 数组和对象 赋值解构
    // 3. 使用数组的slice
    // 4. 使用数组的 concat() 方法

    // 5. 使用递归
    function deep(obj) {
      // 判断要进行拷贝的是对象,还是数组
      var objClone = Array.isArray(obj) ? [] : {};
      // 进行深拷贝的不能为空
      if (obj && typeof (obj) === "object") {
        for (let key in obj) {
          if (obj.hasOwnProperty(key)) {
            if (obj[key] && typeof (obj[key]) === "object") {
              objClone[key] = deep(obj[key]);
            } else {
              objClone[key] = obj[key];
            }
          }
        }
      }
      return objClone;
    }

    // 数组
    var a = [1, 3, 2, 1];
    var b = [];
    // 1. 使用JSON对象的stringify和parse方法
    // b = deepClone(a);
    // 2. 使用es6 数组的解构
    // b = [...a];
    // 3. 使用数组的slice()
    // b = a.slice(0);
    // 4. 使用数组的 concat() 方法
    // b = b.concat(a);
    // 5. 使用递归
    b = deep(a);

    b.push(99);
    console.log(a);
    console.log(b);

    // 对象
    var obj = {
      name: "zpl",
      age: 25,
      friends: ["zz", "pp", "ll"],
      fn: function () {
        console.log(this.name);
      }
    }
    var objb = {};
    // 1. 使用json
    // objb = deepClone(obj);
    // 2. 使用es6 对象的解构
    // objb = {...obj}
    // 5. 使用递归
    objb = deep(obj);

    objb.name = "aj";
    objb.friends.push("99");
    console.log(obj);
    console.log(objb);
    obj.fn();
    objb.fn();

    var fn = function () { }
    var arr = [];
    console.log(typeof (fn));//function
    console.log(typeof (arr));//object

  </script>

 参考:https://www.jianshu.com/p/35d69cf24f1f

posted @ 2020-10-15 23:33  CHUNYIN  阅读(329)  评论(0)    收藏  举报