1.数据类型
- 基本数据类型:名和值都存储在栈内存中;在复制时,栈内存会新开辟一个内存,用来存储新的变量,这个时候修改原变量的值,不会对新生成的变量产生影响。
- 引用数据类型:名存在于栈内存中,值存在于堆内存中,栈内存的会提供一个引用地址指向堆内存中的值。当对引用类型a进行拷贝时(b = a),其实复制的是a的引用地址,而非堆里面的值。当对a里面的数据进行修改时,由于a和b指向的是同一个地址,b自然就受到了影响。这就是所谓的浅拷贝。如果,要是在堆内存中也开辟一个新的内存专门为b存值,就像基本类型那样,就可以达到深拷贝的效果了。
2.实现深拷贝的方法
- 通过递归去复制引用类型的所有层级属性(这里的一些对象如Error、RegExp、Date等都会变成{})
const deepClone = (obj = {}) => {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const objClone = Array.isArray(obj) ? [] : {};
if (typeof obj === 'object') {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 判断ojb子元素是否为对象,如果是,递归复制
if (obj[key] && typeof obj[key] === 'object') {
objClone[key] = deepClone(obj[key]);
} else {
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
- 使用JSON对象的parse和stringify方法实现
function deepClone(obj) {
let _obj = JSON.stringify(obj);
objClone = JSON.parse(_obj);
return objClone
}
这个方法有以下弊端:
- 时间对象(对象=>字符串);
- RegExp、Error对象(对象=>空对象);
- 函数、undefined(丢失);
- NaN、Infinity和-Infinity(=> null);
- 会丢弃constructor
注意:Object.assign是浅拷贝!!!