「JavaScript进阶」一文吃透深浅拷贝
2023-12-03 12:40:14
在我们编写的JavaScript程序中,常常会遇到一些问题,比如:如何将一个对象的属性值拷贝到另一个对象中?如何确保在修改一个对象的属性值时,不会影响另一个对象的属性值?这些问题都与JavaScript中的拷贝操作有关。
在JavaScript中,拷贝操作分为两种:深拷贝和浅拷贝。深拷贝是指将一个对象的属性值和子属性值都拷贝到另一个对象中,而浅拷贝是指仅将一个对象的属性值拷贝到另一个对象中,但不拷贝子属性值。
浅拷贝
浅拷贝是一种简单的拷贝操作,它仅将一个对象的属性值拷贝到另一个对象中。这可以通过使用赋值运算符(=)来实现。
const obj1 = {
name: 'John Doe',
age: 30
};
const obj2 = obj1;
obj2.name = 'Jane Doe';
console.log(obj1); // { name: 'Jane Doe', age: 30 }
在这个示例中,我们将obj1的属性值拷贝到obj2中。然后,我们修改了obj2的name属性值。这时,我们发现obj1的name属性值也发生了变化。这是因为浅拷贝只拷贝了obj1的属性值,并没有拷贝子属性值。因此,当我们修改obj2的name属性值时,也会影响obj1的name属性值。
深拷贝
深拷贝是一种更复杂的拷贝操作,它将一个对象的属性值和子属性值都拷贝到另一个对象中。这可以通过使用递归函数或JSON.parse()和JSON.stringify()函数来实现。
// 使用递归函数实现深拷贝
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const newObj = {};
for (const key in obj) {
newObj[key] = deepCopy(obj[key]);
}
return newObj;
}
const obj1 = {
name: 'John Doe',
age: 30,
address: {
street: '123 Main Street',
city: 'Anytown',
state: 'CA'
}
};
const obj2 = deepCopy(obj1);
obj2.name = 'Jane Doe';
obj2.address.street = '456 Elm Street';
console.log(obj1); // { name: 'John Doe', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA' } }
在这个示例中,我们使用递归函数实现了深拷贝。我们将obj1的属性值和子属性值都拷贝到obj2中。然后,我们修改了obj2的name属性值和address.street属性值。这时,我们发现obj1的属性值没有发生变化。这是因为深拷贝将obj1的属性值和子属性值都拷贝到obj2中,因此修改obj2的属性值不会影响obj1的属性值。
什么时候使用深拷贝,什么时候使用浅拷贝?
浅拷贝和深拷贝各有其优缺点。浅拷贝简单易用,但它只拷贝对象本身的属性值,不会拷贝子属性值。深拷贝更复杂一些,但它会拷贝对象本身的属性值和子属性值。
在实际开发中,我们通常会根据需要选择使用浅拷贝还是深拷贝。如果我们只需要拷贝对象本身的属性值,那么可以使用浅拷贝。如果我们需要拷贝对象本身的属性值和子属性值,那么可以使用深拷贝。
例如,如果我们要拷贝一个表单中的数据,那么可以使用浅拷贝。因为表单中的数据都是基本数据类型,浅拷贝就可以满足我们的需要。如果我们要拷贝一个包含复杂对象的JSON对象,那么可以使用深拷贝。因为JSON对象包含子对象,浅拷贝无法满足我们的需要。