浅复制和深复制
目录
介绍
大家好!
我们经常需要出于不同目的创建变量副本。副本可以分为两种类型:浅层副本和深层副本。在面试中,我们经常会遇到关于浅层副本和深层副本的理解和区别。那么,让我们一起来了解一下这些术语和相关示例吧。
浅复制
浅拷贝方法创建的副本中,源变量和被拷贝变量的引用保持不变。这意味着在一个地方进行的修改会影响两个地方。
以下示例有助于更好地理解:
const first_person = {
name: "Jack",
age: 24,
}
const second_person = first_person;
second_person.age = 25;
console.log(first_person.age); // output: 25
console.log(second_person.age); // output: 25
更改对象的age属性值second_person,也会更改first_person对象的age属性。
现在我们来看另一个例子:
const first_person = {
name: "Jack",
age: 24
};
let second_person = first_person;
second_person = {
name: "Jack",
age: 23
};
console.log(first_person.age); // Output: 24
console.log(second_person.age); // Output: 23
呃,这里发生了什么?🤔 为什么值不一样?
嗯,这里我们并没有改变某个特定属性的值,而是赋值了一个新对象。
深度复制
深拷贝方法创建的副本中,源变量和被拷贝变量的引用完全不同。这意味着,在一个地方进行的修改只会影响正在修改的变量。
现在我们来看一些例子:
如果对象/数组没有嵌套,那么我们可以使用以下方法实现深拷贝:
扩展运算符
如果没有嵌套,使用展开语法可以创建深拷贝。
const first_person = {
name: "Jack",
age: 24,
}
const second_person = { ...first_person };
second_person.age = 25;
console.log(first_person.age); // output: 24
console.log(second_person.age); // output: 25
我们来看看嵌套的情况。
const first_person = {
name: "Jack",
age: 24,
address: {
apartment: "A",
city: "London"
}
};
const second_person = { ...first_person };
second_person.age = 25;
second_person.address.apartment = "N";
console.log(first_person.address.apartment); // output: N
console.log(second_person.address.apartment); // output: N
如果存在嵌套,展开运算符会创建一个浅拷贝。
如果对象/数组是嵌套的,那么我们可以使用以下方法实现深拷贝:
JSON.parse() 和 JSON.stringify()
const first_person = {
name: "Jack",
age: 24,
address: {
apartment: "A",
city: "London"
}
};
const second_person = JSON.parse(JSON.stringify(first_person));
second_person.age = 25;
second_person.address.apartment = "N";
console.log(first_person);
console.log(second_person);
结合这两种方法,即使涉及嵌套也能创建深拷贝。
概括
- 浅拷贝方法创建的副本中,源变量和被拷贝变量的引用保持不变。更改其中一个变量,另一个变量也会随之更改。
- 深拷贝方法创建的副本中,源变量引用和被拷贝变量引用完全不同。更改其中一个变量不会影响另一个变量。
- 像 Array.concat()、Array.from()、Object.assign() 等常用方法创建的是浅拷贝。
- Spread(...) 运算符在没有嵌套时会创建深拷贝。
- 创建深拷贝的方法之一是使用 JSON.parse() 和 JSON.stringify()。
参考
- https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy
- https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy
