最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Object对象的浅拷贝与深拷贝方法详解

    正文概述 掘金(赖先生)   2020-11-24   589

    关注公众号: 微信搜索 web全栈进阶 ; 收货更多的干货

    对象的深拷贝与浅拷贝的区别如下:

    • 浅拷贝:仅仅复制对象的引用,而不是对象本身; 修改值相互影响;
    • 深拷贝:把复制的对象所引用的全部对象都复制一遍; 修改值不会相互影响。

    一、浅拷贝

    • Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。 它将返回目标对象 (简单粗暴明了 推荐首选)
    • 详情直戳 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
    function test() {
        'use strict';

        let obj1 = { a: 0 , b: { c: 0}};
        let obj2 = Object.assign({}, obj1);
        console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
      
        obj1.a = 1;
        console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
        console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
      
        obj2.a = 2;
        console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
        console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
      
        obj2.b.c = 3;
        console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
        console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
      
        // Deep Clone 
        obj1 = { a: 0 , b: { c: 0}};
        let obj3 = JSON.parse(JSON.stringify(obj1));
        obj1.a = 4;
        obj1.b.c = 4;
        console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}

        // 拷贝单个对象 
        var obj = { a: 1 };
        var copy = Object.assign({}, obj);
        console.log(copy); // { a: 1 }  

        // 合并多个对象
        let o1 = { a: 1 };
        let o2 = { b: 2 };
        let o3 = { c: 3 };

        let obj = Object.assign(o1, o2, o3);
        console.log(obj); // { a: 1, b: 2, c: 3 }
        console.log(o1);  // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变
    }

    // 需要注意的是浅拷贝的话当自身或者目标对象改变两者皆会改变  (希望不改变则需要深拷贝)
    test();

    二、深拷贝

    要实现深拷贝有很多办法,有最简单的 JSON.parse() 方法,也有常用的递归拷贝方法,和ES5中的 Object.create() 方法。

    - 方法一:使用 JSON.parse() 方法

     function deepClone(initalObj) {
          var obj = {};
          try {
              obj = JSON.parse(JSON.stringify(initalObj));
          }
          return obj;
      }
      var obj = {
          a: {
              a: "world",
              b: 21
          }
      }
      var cloneObj = deepClone(obj);
      cloneObj.a.a = "changed";
      console.log(obj.a.a); // "world"

    缺点:

    • 该方法会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object
    • 这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

    - 方法二:递归拷贝

    为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。

    // 深拷贝 递归1.1 写法一
    function deepClone(obj) {
        var obj = {};
        for (var i in initalObj) {
            var prop = initalObj[i];
            // 避免相互引用对象导致死循环,
            if(prop === obj) {
                continue;
            }
            if (typeof prop === 'object') {
                obj[i] = (prop.constructor === Array) ? [] : {};
                arguments.callee(prop, obj[i]);
            } else {
                obj[i] = prop;
            }
        }
        return obj;
    }
    // 深拷贝 递归1.2 写法二
    function deepCopy(p, c) {
      var c = c || {};
      for (var i in p) {
        if (typeof p[i] === 'object') {
          c[i] = (p[i].constructor === Array) ? [] : {};
          deepCopy(p[i], c[i]);
        } else {
           c[i] = p[i];
        }
      }
      return c;
    }
    // 深拷贝 递归1.3 写法二  比较全面的写法 参考至 (https://mp.weixin.qq.com/s/vXbFsG59L1Ba0DMcZeU2Bg)
    function forEach(array, cloneTarget) {
      let index = -1;
      const length = array.length;
      while (++index < length) {
        cloneTarget(array[index], index);
      }
      return array;
    }

    function clone(target, map = new WeakMap()) {
      if (typeof target === 'object') {
        const isArray = Array.isArray(target);
        let cloneTarget = isArray ? [] : {};
        if (map.get(target)) {
          return target;
        }
        map.set(target, cloneTarget);
        const keys = isArray ? undefined : Object.keys(target);
        forEach(keys || target, (value, key) => {
          if (keys) key = value
          cloneTarget[key] = clone(target[key], map);
        });
        return cloneTarget;
      } else {
        return target;
      }
    }
    2.3 方法三:集合Object.assign()方法
    // 深拷贝
    function deepClone(initalObj) {
        var obj = {};
        for (var i in initalObj) {
            var prop = initalObj[i];
            // 避免相互引用对象导致死循环
            if(prop === obj) {
                continue;
            }
            if (typeof prop === 'object') {
                obj[i] = Object.assign(prop);
            } else {
                obj[i] = prop;
            }
        }
        return obj;
    }

    深拷贝1.3版本参考至: https://mp.weixin.qq.com/s/vXbFsG59L1Ba0DMcZeU2Bg (递归方法总结的很全面推荐)


    起源地下载网 » Object对象的浅拷贝与深拷贝方法详解

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元