返回
“多维解析”JS中的深拷贝:揭秘浅谈背后的真谛
前端
2024-01-21 02:58:12
深入浅出,剥丝抽茧解深拷贝
JavaScript中的数据类型可分为基本类型和引用类型。基本类型包括字符串、数字、布尔值等,它们的值存储在栈内存中;引用类型包括对象、数组、函数等,它们的值存储在堆内存中,通过引用来访问。当对引用类型进行赋值操作时,实际上是将变量的指针指向了堆内存中的对象。
浅拷贝是指对引用类型进行赋值操作时,仅仅复制其指针,指向堆内存中同一块地址。这意味着对浅拷贝副本的修改会影响原始对象,反之亦然。
深拷贝是指对引用类型进行赋值操作时,会在堆内存中重新开辟一块内存地址,将原始对象的值完全复制过来存放起来。这意味
着深拷贝副本与原始对象完全独立,不受互相影响。
实战演练,揭秘深拷贝的多种实现方式
方法一:使用JSON.parse()和JSON.stringify()
const obj = { name: 'John', age: 30 };
// 使用JSON.stringify()将对象转换成JSON字符串
const jsonStr = JSON.stringify(obj);
// 使用JSON.parse()将JSON字符串转换成对象
const newObj = JSON.parse(jsonStr);
console.log(newObj); // { name: 'John', age: 30 }
console.log(obj === newObj); // false
方法二:使用Object.assign()
const obj = { name: 'John', age: 30 };
// 使用Object.assign()将对象的值复制到另一个对象中
const newObj = Object.assign({}, obj);
console.log(newObj); // { name: 'John', age: 30 }
console.log(obj === newObj); // false
方法三:使用递归
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(item => deepCopy(item));
}
const newObj = {};
for (const key in obj) {
newObj[key] = deepCopy(obj[key]);
}
return newObj;
}
const obj = { name: 'John', age: 30, hobbies: ['coding', 'reading'] };
const newObj = deepCopy(obj);
console.log(newObj); // { name: 'John', age: 30, hobbies: ['coding', 'reading'] }
console.log(obj === newObj); // false
灵活运用,深拷贝的进阶技巧
情景一:对象包含循环引用
循环引用是指两个或多个对象相互引用,导致无法释放内存的情况。在深拷贝的过程中,如果遇到循环引用,需要特殊处理。可以使用WeakMap或Set来存储已复制过的对象,当再次遇到循环引用时,直接返回WeakMap或Set中存储的对象即可。
情景二:对象包含不可序列化的属性
有些属性,如函数、正则表达式、Symbol等,是不可序列化的。在深拷贝的过程中,遇到不可序列化的属性时,需要特殊处理。可以将不可序列化的属性删除或替换为可序列化的值。
结语
深拷贝在JavaScript中扮演着重要的角色,它可以帮助我们创建对象副本,而不影响原始对象。理解深拷贝的机制和应用场景,可以帮助我们编写出更加可靠和高效的代码。