详解JavaScript对象的深浅复制

  

  

从层次上来看,对象的复制可以简单地分为浅复制和深复制,顾名思义,浅复制是指只复制一层对象的属性,不会复制对象中的对象的属性,对象的深复制会复制对象中层层嵌套的对象的属性。
  

  

在复制对象时,除了要复制对象的属性外,还要兼顾到是否保留了对象的构造函数属性,是否对每一种数据类型(JavaScript常见的数据类型有字符串、数字、布尔值、数据,正则表达式,数组,函数,对象)都实现正确的复制。项目中,我们可以根据实际情况,决定需要实现什么样程度的复制。
  

  

本文是我在复制对象方面的一些心得总结,由浅复制到深复制,由只复制简单属性到复制功能、正则表达式等复杂属性,层层递进。如有陈述不当之处,烦请指出,不胜感激。

  

  

<强>浅复制

  

浅复制只会依次复制对象的每一个属性,不会对这些属性进行递归复制。下面是一个简单的浅复制实现。

     //对象浅复制   函数shadowCopy (obj) {   如果(typeof obj !=='对象')返回obj;   (var道具obj) {   如果(obj.hasOwnProperty(道具)){   newObj[支持]=obj(道具);   }   }   返回newObj;   }      

仔细观察,不难发现上述方法的缺陷:

  

1。不能正确实现数组的浅复制

  

2。复制操作丢失了对象的构造函数属性

  

好,我们现在已经发现了问题所在,只需针对性地解决,一个还算完美的浅复制对象的方法就诞生了!

     //对象浅复制   函数shadowCopy (obj) {   如果(typeof obj !=='对象')返回;   var newObj;//保留对象的构造函数属性   如果(obj。构造函数===数组){   newObj=[];   其他}{   newObj={};   newObj。构造函数=obj.constructor;   }   (var道具obj) {   如果(obj.hasOwnProperty(道具)){   newObj[支持]=obj(道具);   }   }   返回newObj;   }      

浏览器中测试一下:

        var arr1=(0, 1, 2);   console.log (arr1);   console.log (shadowCopy (arr1));   var arr2=[0, 1, 2, [3、4、5]],   arr2Copy=shadowCopy (arr2);   console.log (arr2);   console.log (arr2Copy);   arr2Copy [3] [0]=6;   console.log (arr2 [3] [0]);//6      

详解JavaScript对象的深浅复制

  

好!可以正确实现数组复制和并且保留构造函数了,但细心的你一定发现了,浅复制后的对象的arr2Copy[3]和arr2[3]指向的是一个对象,改变其中一个,同时也会改变另一个。我们想要实现的是复制,但这并不是复制呀!
  这是浅复制的一个弊端所在,接下让我们看看深复制是怎样解决这个问题的。

  

<强>深复制

  

深复制需要层层递归,复制对象的所有属性,包括对象属性的属性的属性....(晕~)
  如果只是需要简单地复制对象的属性,而不用考虑它的构造函数,也不用考虑函数,正,则数据等特殊数据类型,那这里有一个深复制的小技巧,两行代码即可:

        函数deepCopy (obj) {   如果(typeof obj !==岸韵蟆?{返回;}   var str=JSON.stringify (obj);   返回JSON.parse (str);   }      

大多数情况下,上面的就可以满足要求了,但一些时候,我们需要把函数,正则等特殊数据类型也考虑在内,或者当前环境不支持JSON时,上面的方法也就不适用了。这时,我们可以通过递归来实现对象的深层复制,如下:

        函数deepCopy (obj) {   如果(typeof obj !==岸韵蟆?{返回;}   var newObj;//保留对象的构造函数属性   如果(obj。构造函数===数组){   newObj=[];   其他}{   newObj={};   newObj。构造函数=obj.constructor;   }   (var道具obj) {   如果(typeof obj[支持]==='对象'){   如果(obj[支持]。构造函数===RegExp | | obj[支持]。构造函数===日期){   newObj[支持]=obj(道具);   其他}{//递归   newObj[支持]=deepCopy (obj[支持]);   }   其他}{   newObj[支持]=obj(道具);   }   }   返回newObj;   }      

先用上面的例子测试:

  

详解JavaScript对象的深浅复制

  

棒!可以正确实现多维数组的复制,再看是否能实现函数和正则的复制:

详解JavaScript对象的深浅复制