深拷贝的实现
什么是深拷贝?
深拷贝与浅拷贝最大的不同就在于,当遇到属性值为引用类型的时候,它会新建一个引用类型并将对应的值复制给它,因此新对象获得的一个是新的引用类型而不是原有类型的引用。
深拷贝对于一些对象可以使用 JSON 的两个函数来实现,但是由于 JSON 的对象格式比 js 的对象格式更加严格,所以如果属性值里边出现函数或者 Symbol 类型的值时,会转换失败。
代码实现
JSON.stringify()
JSON.parse(JSON.stringify(obj))是目前比较常用的深拷贝方法之一,它的原理就是利用JSON.stringify()将js对象序列化(JSON字符串),再使用JSON.parse()来反序列化(还原)js对象。- 这个方法可以简单粗暴地实现深拷贝,但是还存在问题,要拷贝的对象中如果有函数,undefined 或 symbol,当使用过
JSON.stringify()进行处理之后,都会消失。
js
let obj1 = { a: 0,
b: {
c: 0
}
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.a = 1;
obj1.b.c = 1;
console.log(obj1); // {a: 1, b: {c: 1}}
console.log(obj2); // {a: 0, b: {c: 0}}手写实现
思路:
- 遍历源对象的所有属性。
- 对于每个属性,如果是基本类型,则直接赋值给目标对象。
- 如果是引用类型(如对象或数组),则递归调用深拷贝函数,创建一个新的对象或数组,并将属性值复制到新的对象或数组中。
js
function deepCopy(obj) {
// 检查是否是基本类型
if (obj === null || typeof obj !== 'object') {
return obj;
}
// 创建目标对象
let copy;
if (Array.isArray(obj)) {
// 如果是数组,创建一个空数组
copy = [];
} else {
// 如果是对象,创建一个空对象
copy = {};
}
// 遍历源对象的属性
for (let key in obj) {
// 这里使用了 hasOwnProperty,是为了过滤掉原型链上的属性,保证只对对象本身的属性进行深拷贝
if (obj.hasOwnProperty(key)) {
// 对于每个属性,递归调用深拷贝函数
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
Blog of Desain