浅拷贝
浅拷贝是指创建一个新对象,将原始对象的属性值复制到新对象中。
如果属性是基本数据类型,那么直接复制其值;如果属性是对象或数组等引用类型,复制的是它们的引用而不是值。
function shallowCopy(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
const newObj = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
};
key在每次迭代中都只是一个迭代变量,而不是需要重新分配的变量。使用const可以确保key在每次迭代中不会被重新赋值,增加代码的可读性和安全性。
深拷贝
深拷贝是指创建一个新对象,递归地复制原始对象及其所有嵌套的对象,确保原始对象及其副本之间的完全隔离。这样,修改新对象中的属性不会影响原始对象,反之亦然。
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
const newObj = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = deepCopy(obj[key]);
}
}
return newObj;
};
用例
// 复杂用例:
const complexObject = {
name: 'John',
age: 30,
address: {
street: '123 Main St',
city: 'Cityville',
country: 'Countryland'
},
hobbies: ['reading', 'playing guitar'],
friends: [
{ name: 'Alice', age: 28 },
{ name: 'Bob', age: 32 }
]
};
// 测试浅拷贝
const shallowCopyResult2 = shallowCopy(complexObject);
console.log(shallowCopyResult2);
shallowCopyResult2.name = 'Oliver';
shallowCopyResult2.age = 28;
shallowCopyResult2.address.city = 'Villageton';
shallowCopyResult2.hobbies.push('hiking');
shallowCopyResult2.friends[0].name = 'Eva';
console.log(complexObject); // name和age不变,上面三个操作起作用
console.log(shallowCopyResult2);
// 测试深拷贝
const deepCopyResult2 = deepCopy(complexObject);
console.log(deepCopyResult2);
deepCopyResult2.address.city = 'Huston';
deepCopyResult2.hobbies.push('swimming');
deepCopyResult2.friends[0].name = 'Elen';
console.log(complexObject); // 上面三个操作不起作用
console.log(deepCopyResult2);
在JavaScript中,对象的比较是基于引用的。 使用===运算符比较两个对象时,它会检查这两个对象是否指向内存中的相同位置,而不是它们的内容是否相同。
// 简单用例
const obj = { a: 1, b: { c: 2 } };
// 测试浅拷贝
const shallowCopyResult1 = shallowCopy(obj);
console.log(shallowCopyResult1); // 应输出 { a: 1, b: { c: 2 } }
console.log(shallowCopyResult1 === obj); // shallowCopyResult1 和 obj 是两个不同的对象,应输出 false
console.log(obj.a === shallowCopyResult1.a); // shallowCopyResult1 中的属性 a 是基本类型,值相等,应输出 true
console.log(obj.b === shallowCopyResult1.b); // shallowCopyResult1 中的属性 b 是引用类型(对象),浅拷贝只复制引用,应输出 true
console.log(obj.b.c === shallowCopyResult1.b.c); // obj.b.c 和 shallowCopyResult1.b.c 都是基本类型,值相等,应输出 true
// 测试深拷贝
const deepCopyResult1 = deepCopy(obj);
console.log(deepCopyResult1); // 应输出 { a: 1, b: { c: 2 } }
console.log(deepCopyResult1 === obj); // deepCopyResult1 和 obj 是两个不同的对象,应输出 false
console.log(obj.a === deepCopyResult1.a); // deepCopyResult1 中的属性 a 是基本类型,值相等,应输出 true
console.log(obj.b === deepCopyResult1.b); // deepCopyResult1 中的属性 b 是引用类型(对象),深拷贝会递归复制,应输出 false
console.log(obj.b.c === deepCopyResult1.b.c); // obj.b.c 和 deepCopyResult1.b.c 都是基本类型,值相等,应输出 true
// 修改原始对象
obj.a = 100;
obj.b.c = 200;
console.log(obj); // 应输出 { a: 100, b: { c: 200 } }
console.log(shallowCopyResult1); // shallowCopyResult1 中的 a 仍然是原值 1,但 b 引用的是原始对象 obj 中的 b,所以 b.c 被修改为 200。应输出 { a: 1, b: { c: 200 } }
console.log(deepCopyResult1); // deepCopyResult1 是深拷贝,不受 obj 修改的影响,保持原样。应输出 { a: 1, b: { c: 2 } }