深浅复制的简单定义如下:
深复制:直接将数据复制给对应的变量;
浅复制:将数据的地址复制给对应的变量;
js的数据类型有Number,Boolean,String,Null,Undefined,Object五种类型,Object又包含Function,Array和Object自身。前面的五种类型叫做基本类型,而Object是引用类型。我们现在为什么要提到数据类型呢?先看以下几个例子。
Test1:
var a = [0,1,2,3];
var a1= a;
alert(a1);//[0,1,2,3]
a[1]="白";
alert(a1);//[0,"白",2,3]
将a赋值给a1,当a的值改变的时候,a1发生了变化。
Test2:
Var a = "dong";
var a1 = a;
alert(a1);//dong;
a="abc";
alert(a1);//dong;
将a赋值给a1,当a的值改变时,a1却没有发生变化。
几乎相同的代码居然会有不同的效果,这是为什么呢?由于前面的是字符串,后面的数组。好像就是我们前面提到的基本类型和数据类型吧。那我们把数据类型换一下看看会有什么结果。
Test3:
var a = {w1:2,w2:3}
var a1= a;
alert(a1);//{w1:2,w2:3}
a1.w1="菲";
alert(a);//{w1:"菲",w2:3}
Test4:
var a = 1234;
var a1 = a;
alert(a1);//1234
a=888;
alert(a1);//1234
在这两组代码中,我们把数据类型分别换成了Number型和Object类型。Test4中可以发现a1不随a值的变化而变化,Test3 中a会随着a1的变化而变化(这里和Test1略有不同,改变的是a1,当然你改变a的话,a1也会跟着变化)
于是得出个一般性的结论了:
js中基本类型的赋值为深复制,而引用类型的赋值为浅复制。
现在有必要把深复制和浅复制的定义扩展一下了。
浅复制:就是把数据的地址赋值给对应变量,而没有把具体的数据复制给变量,变量会随数据值的变化而变化。
深复制:就是把数据赋值给对应的变量,从而产生一个与源数据不相干的新数据(数据地址已变化)。
Test5:
var a = {w1:2,w2:3}
var a1= a;
alert(a1);//{w1:2,w2:3}
var a={x1:7,x2:8}
alert(a1);//{w1:2,w2:3}
此处为浅复制,a1应该随着a的变化而变化呀,但是并没有出出现浅复制的现象,此处就是引用类型导致的问题。对象赋值其实都是引用传值,传递的是一个地址。那么test5中的第四行其实就是把变量a指向了一个新的地址。而a1还是指向的原来那个地址,原来地址中的值没变,所以a1就不会变。所以请记住:浅复制不会随着存储数据地址的变化而变化,只会随着数据值的变化而变化。
为了实现引用类型的深度复制,其实就是深度克隆了。例如
function clone(obj){
var o=[];
if(obj.constructor== Array) {
o=obj.slice(0);
}else{
o={};
for(var i in obj){
o[i] = typeof obj[i] === "object" ? obj[i].clone() : obj[i];}
}
return o;
}