在 JavaScript 中,浅拷贝和深拷贝是两种不同的方式来复制对象或数组的内容。它们在复制嵌套对象或数组时表现出不同的行为。
浅拷贝
复制后的对象会与原对象共用内存地址,会互相干扰
常用浅拷贝
let a = {
age: 20
};
let b = a;
b.age = 30;
console.log(a.age); // 30
使用 Object.assign() 进行浅拷贝
const originalObject = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, originalObject);
console.log(shallowCopy); // { a: 1, b: { c: 2 } }
shallowCopy.a = 100; // 修改复制后的对象的属性
shallowCopy.b.c = 200; // 修改复制后对象的嵌套对象属性
console.log(originalObject); // { a: 1, b: { c: 200 } }
console.log(shallowCopy); // { a: 100, b: { c: 200 } }
在上面的示例中,Object.assign() 创建了 shallowCopy,但它仍然引用了 originalObject 中的嵌套对象。
深拷贝
复制的对象会创建一个新的内存地址,原对象内存地址的属性会复制到新对象的内存地址,互不干扰
利用JSON类
就是将一个对象转为JSON字符串,再转回JSON对象
let a = {
age: 20
};
let b = JSON.parse(JSON.stringify(a));
console.log(b.age); // 20
b.age = 30;
console.log(a.age); // 20
console.log(b.age); // 3
- 优点:方便快捷,性能相对比较好
- 缺点:复杂的对象进行JSON转换有可能会丢失属性,如下代码
let a = {
age: 20,
local: function() {
return 5;
}
};
let b = JSON.parse(JSON.stringify(a));
console.log(b); // { age : 20 }
console.log(b.local()); // b.loacl is not a function
使用递归进行深拷贝
以下是一个简单的深拷贝示例,使用递归方法:
function deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj; // 如果是基本类型或 null,则直接返回
}
if (Array.isArray(obj)) {
// 如果是数组,递归复制每个元素
return obj.map(item => deepClone(item));
}
// 如果是对象,递归复制每个属性
const clonedObj = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
const originalObject = { a: 1, b: { c: 2 } };
const deepCopy = deepClone(originalObject);
console.log(deepCopy); // { a: 1, b: { c: 2 } }
deepCopy.a = 100; // 修改复制后的对象的属性
deepCopy.b.c = 200; // 修改复制后对象的嵌套对象属性
console.log(originalObject); // { a: 1, b: { c: 2 } }
console.log(deepCopy); // { a: 100, b: { c: 200 } }
在上述示例中,deepClone 函数递归地复制对象及其嵌套结构,创建一个完全独立的深拷贝。
需要注意的是,深拷贝可能会更消耗内存和计算资源,特别是在处理大型嵌套结构时。因此,在选择浅拷贝和深拷贝之间,需要根据具体需求权衡性能和复制结果。如果确实需要完全独立的副本,那么深拷贝是合适的选择。