深拷贝和浅拷贝的异同以及实现方式

JavaScript016

深拷贝和浅拷贝的异同以及实现方式,第1张

相同点:

深拷贝和浅拷贝都是用于对复杂数据类型进行复制。

差异:

其区别在于深拷贝是对原数据进行递归复制,并存到一个新地址,从而使新老数据互不影响。

而浅拷贝只是对原数据的地址进行拷贝,从而会使新老数据相互影响。

常用实现方法:

深拷贝:

1.递归复制(全部适用)

function duplicate(obj) {

var newObj = null

If(obj !== null &&typeof(obj)==obj){

newObj=Obj instanceof Array?[]:{}

For (var i in obj){

newObj[i] = duplicate[i]

}

}else{

newObj = obj

}

return newObj

}

2.JSON.stringify(obj)

关于这个方法有一个缺点就是 不能拷贝function和undefine( 在火狐上直接报错error,而在谷歌上会直接忽略掉相关属性) 。因为这是通过把数据转化为字符串的形式赋值给一个新地址。

浅拷贝:

1.函数实现

function simpleDuplicate(obj){

Var newObj ={};

for(var I in obj){

If(obj.hasOwnProperity[i]){

newObj[i] = obj[i]

}

}

return newObj

}

2.各种赋值、合并删除操作。

1、浅拷贝可以使用列表自带的copy()函数(如list.copy()),或者使用copy模块的copy()函数。深拷贝只能使用copy模块的deepcopy(),所以使用前要导入:from copy import deepcopy。

2、 如果拷贝的对象里的元素只有值,没有引用,那浅拷贝和深拷贝没有差别,都会将原有对象复制一份,产生一个新对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开。

3、 如果拷贝的对象里的元素包含引用(像一个列表里储存着另一个列表,存的就是另一个列表的引用),那浅拷贝和深拷贝是不同的,浅拷贝虽然将原有对象复制一份。

但是依然保存的是引用,所以对新对象里的引用里的值进行修改,依然会改变原对象里的列表的值,新对象和原对象完全分离开并没有完全分离开。而深拷贝则不同,它会将原对象里的引用也新创建一个,即新建一个列表,然后放的是新列表的引用,这样就可以将新对象和原对象完全分离开。

浅拷贝就是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级。

深拷贝和浅拷贝,主要是对象发生复制的时候,根据复制的层级不同来区分的。很多人在这里经常变量赋值发生混淆。对于JavaScript数组等复杂的数据类型来说,将其赋值给其它变量,其实只是复制了对象的地址给它,两个变量指向的是同一个对象,因此普通的赋值既不是深拷贝也不是浅拷贝。

深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:

在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去。

而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。