Object对象的浅拷贝与深拷贝方法详解

/* ===================== 直接看代码 ===================== */
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <h1>http://www.codeceo.com/article/javascript-object-deep-copy.html</h1>
  <p>
    对象的深拷贝与浅拷贝的区别如下:
    浅拷贝:仅仅复制对象的引用,而不是对象本身;
    深拷贝:把复制的对象所引用的全部对象都复制一遍。
  </p>
  一. 浅拷贝的实现
<script type="text/javascript">
   /* ================ 浅拷贝 ================ */
  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();
 
   
</script>
<script type="text/javascript">
  二. 深拷贝的实现
  要实现深拷贝有很多办法,有最简单的 JSON.parse() 方法,也有常用的递归拷贝方法,和ES5中的 Object.create() 方法。
  
2.1 方法一:使用 JSON.parse() 方法   要实现深拷贝有很多办法,比如最简单的办法是使用 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对象是无法通过这种方式深拷贝。
  2.2 方法二:递归拷贝   为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。   版代码如下:
 /* ================ 深拷贝 写法一: ================ */
  function deepClone(initalObj, finalObj) {
      var obj = finalObj || {};
      for (var i in initalObj) {
          var prop = initalObj[i];
          // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
          if(prop === obj) {
              continue;
          }
          if (typeof prop === 'object') {
              obj[i] = (prop.constructor === Array) ? [] : {};
              arguments.callee(prop, obj[i]);
          } else {
              obj[i] = prop;
          }
      }
      return obj;
  }
 
/* ================ 深拷贝 写法二: ================ */
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;
}
 
   
 
   
  
  2.3 方法三:使用Object.create()方法   直接使用 var newObj = Object.create(oldObj),可以达到深拷贝的效果。   /* ================ 深拷贝 ================ */   function deepClone(initalObj, finalObj) {   var obj = finalObj || {};   for (var i in initalObj) {   var prop = initalObj[i];   // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况   if(prop === obj) {    continue;   }   if (typeof prop === 'object') {   obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);    } else {   obj[i] = prop;   }   }   return obj;   } </script> </body> </html>

有问题或者有bug非常欢迎留言指正。

转载于:https://www.cnblogs.com/ljx20180807/p/9790239.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值