js中浅拷贝和深拷贝

简介

深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。

浅拷贝

实现代码:

1
2
3
4
5
6
7
function extendCopy(p){
var c={};
for(var attr in p){
c[attr]=p[attr];
}
return c;
}

实例:

1
2
3
4
5
6
7
var a={
num:10,
arr:[1,2,3]
}

var b=extendCopy(a);
console.log(b);

结果:

此时,b已经继承了a的属性。

问题

实际上,JavaScript 存储对象都是存地址的,浅拷贝只是增加了一个指针指向已经存在的内存,就是说此时a.arr和b.arr指向同一个地址。如果改变其中一个的值,另一个也会改变。如下:

1
2
b.arr.push(4);
console.log(a);

向b中的arr添加一项,再打印a,结果:

发现,改变b的arr,a也相应改变了。这带来不方便,我们不希望它们之间存在这种联系。

深拷贝

对于浅拷贝存在的问题,可以通过深拷贝去除。

实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
function deepCopy(p, c) {
var c = c || {}; //c等于自身或者{}
for(var attr in p){
if(typeof p[attr]==='object'){
c[attr]=(p[attr].constructor===Array)?[]:{};
deepCopy(p[attr],c[attr]);
}else{
c[attr]=p[attr];
}
}
return c;
}

实例:

1
2
3
4
5
6
7
var a={
num:10,
arr:[1,2,3]
}

var b=deepCopy(a,b);
console.log(b);

结果:

这时,再来改变一下b,看看a是否改变:

1
2
3
b.arr.push(5);
console.log(b);
console.log(a);

结果:

显然,此时b的arr多了一项5,而a没有改变。