提出问题
问题:在拷贝之后,为什么修改a数组里的数据,b数组也会变?
解决问题
从这个问题发散开来,我们首先要弄明白的是以下几个知识点,从而弄清楚造成这个问题的原因:
知识点1:js的数据类型和拷贝方式
- | 基本数据类型 | 引用数据类型 |
---|---|---|
number,string,boolean,null,undefinded | object,array,function | |
数据存储 | 值存在栈内存中 | 值存在堆内存中,地址存在栈内存中 |
拷贝 | 拷贝值 | 拷贝指向堆内存的地址 |
拷贝方式 | 栈内存中开辟新内存,存储变量和值 | 栈内存中开辟新内存存储变量和堆内存的地址,和原拷贝对象指向同一个堆内存中的值 |
修改是否影响原拷贝对象 | 否 | 是 |
如图,对于基本数据类型而言
拷贝前:
拷贝后:
故修改b的值,不会影响a的值
而对于引用数据类型
拷贝前:
拷贝后:
故修改d的值会影响到原拷贝对象c,这种拷贝方式其实就是浅拷贝
知识点2:深拷贝和浅拷贝
其实,只有在针对引用数据的拷贝的时候,才会存在浅拷贝的问题,浅拷贝会影响到原拷贝对象的数据安全,故不能通过直接赋值的方式来拷贝。那么,应该怎么拷贝呢?考虑是,只要在堆内存中新开辟一块地方来存值,其实就对原拷贝对象产生不了影响了,所以深拷贝就是,新建了一个对象/数组,然后递归去复制原对象/数组的所有层级属性。
由此封装的深拷贝函数:
function deepCopy(oldObj) {
var newObj = {};
for(var key in oldObj) {
if(typeof oldObj[key] === 'object') {
newObj[key] = deepCopy(oldObj[key]);
}else{
newObj[key] = oldObj[key];
}
}
return newObj;
}