拷贝其实本质上就是复制,也就是为了用来复制数据,深浅拷贝之间最大的区别就是:复制出来的数据的值是否会因为原来元素的改变而改变,深拷贝可以理解为,它的更深层次也被重新复制了一份数据,做了深层的工作,而浅拷贝只是做了表面的工作,对于他深层的元素并没有进行处理,这样是不是就更容易理解了呢?
浅拷贝:仅仅是复制了引用(地址),相互之间会影响
深拷贝:在堆中重新分配了内存,不同地址,相同的值,不会互相影响
eg:
有一个对象:
var obj = {
name: "王",
age: 18,
sex: "男",
girlFriend: {
name: "张",
age: 16,
sex: "女",
},
};
如上述代码所示,可以发现该对象中存在一个对象属性,那此时如果要得到一个obj1=obj,也就是对obj复制一份数据保存在obj1中,首先最简单的方法很容易让人想到的就是通过循坏给obj1每一项赋值,即obj1[i]=obj[i],代码实现如下:
var obj1 = {};
for (var i in obj) {
obj1[i] = obj[i];
}
console.log(obj1);
obj.girlFriend.name = "王";
console.log(obj1.girlFriend.name);
此时,修改了obj的girlFriend的name,输出结果后会发现obj1的girlFriend的name也同时被修改了,这就说明了obj中的girlFriend这个属性值对象并没有被重新开辟一块存储空间被复制,而仅仅是从表面看被复制了,其实obj1与obj的girlFriend属性对象只是指向了同一个存储空间,才导致obj1与obj具有了相同的值,这就是所谓的浅拷贝,只做了表面的工作,而至于要复制的数据里面的引用类型数据并没有做到真正的复制工作。
那如何才能进行深拷贝呢?很容易想到的是:浅拷贝仅仅是对于它本身就是值类型的属性值时进行的拷贝会被重新赋值,那如果它内层的引用类型时我们也可以分解成一个个属性值(不再是一整个引用类型),那对它进行循坏复制不就可以了吗?所以这里就很容易可以想到递归,子问题的处理方式与父问题处理问题方式相同,所以深拷贝的解题思路不就迎刃而解了吗?
代码如下:
function deepCopy(obj) {
var obj1 = {};
for (var i in obj) {
if (typeof obj[i] === "object") {
obj1[i] = deepCopy(obj[i]);
} else {
obj1[i] = obj[i];
}
}
return obj1;
}
var obj1 = deepCopy(obj);
console.log(obj1);
obj.girlFriend.age = 15;
console.log(obj1.girlFriend.age);
console.log(typeof obj);
通过代码可以发现,此时对obj的girlFriend的属性值进行修改时,并不会导致obj1中的girlFriend中属性值的变化,所以这样就做到了深拷贝,对它里层的引用类型也做到了真正的拷贝工作,无论它有几层都无所谓,递归可以解决到每一层。