返回
你不会的JS深浅拷贝,面试必挂!
前端
2022-11-27 05:45:34
浅拷贝与深拷贝:深入理解 JavaScript 对象复制
摘要:
浅拷贝和深拷贝是两种不同的技术,用于在 JavaScript 中复制对象。浅拷贝复制一个对象的引用,而深拷贝创建一个新的对象并复制其所有属性值,包括嵌套的对象。了解这两种技术的区别对于编写可靠和高效的 JavaScript 代码至关重要。
浅拷贝
定义:
浅拷贝创建一个新对象,并将其直接属性从源对象复制到该对象。这意味着新对象将引用源对象的嵌套对象。
优点:
- 性能优于深拷贝
- 适用于简单对象(如字符串、数字、布尔值)
缺点:
- 更改新对象的嵌套对象属性也会影响源对象
- 无法复制原型链
方法:
- Object.assign(): 创建一个新对象,并使用源对象作为参数。
- 扩展运算符(...): 创建一个新对象,并使用源对象作为扩展运算符的参数。
示例:
const obj1 = {
name: "John Doe",
age: 30,
address: {
street: "123 Main Street",
city: "Anytown",
},
};
const obj2 = Object.assign({}, obj1);
obj2.name = "Jane Doe";
obj2.address.city = "New York";
console.log(obj1); // { name: "John Doe", age: 30, address: { street: "123 Main Street", city: "New York" } }
console.log(obj2); // { name: "Jane Doe", age: 30, address: { street: "123 Main Street", city: "New York" } }
深拷贝
定义:
深拷贝创建一个新对象,并递归复制源对象的属性值,包括嵌套的对象。它创建新对象的副本,与源对象没有共享引用。
优点:
- 更改新对象不会影响源对象
- 可以复制原型链
缺点:
- 性能较差
- 可能导致堆栈溢出错误,如果源对象包含循环引用
方法:
- JSON.parse(JSON.stringify()): 将源对象转换为 JSON 字符串,然后再将其解析回一个新对象。
- 递归函数: 编写一个函数来遍历源对象并创建其副本。
示例:
const obj1 = {
name: "John Doe",
age: 30,
address: {
street: "123 Main Street",
city: "Anytown",
},
};
const obj2 = JSON.parse(JSON.stringify(obj1));
obj2.name = "Jane Doe";
obj2.address.city = "New York";
console.log(obj1); // { name: "John Doe", age: 30, address: { street: "123 Main Street", city: "Anytown" } }
console.log(obj2); // { name: "Jane Doe", age: 30, address: { street: "123 Main Street", city: "New York" } }
浅拷贝与深拷贝的比较
特性 | 浅拷贝 | 深拷贝 |
---|---|---|
复制范围 | 直接属性 | 所有属性值(包括嵌套对象) |
性能 | 更快 | 更慢 |
引用 | 创建一个新对象,指向源对象的嵌套对象 | 创建一个新对象,不共享引用 |
用途 | 适用于简单对象、性能优先 | 适用于复杂对象、数据完整性优先 |
何时使用浅拷贝和深拷贝
浅拷贝:
- 当您需要快速复制一个简单对象时
- 当您希望更改副本不会影响源对象时
深拷贝:
- 当您需要复制一个复杂对象,其中包含嵌套对象和循环引用时
- 当您需要确保更改副本不会影响源对象时
常见问题解答
1. 什么是浅拷贝的优点?
浅拷贝的优点是性能优异,因为它只是复制直接属性的引用。
2. 什么是深拷贝的缺点?
深拷贝的缺点是性能较差,并且可能导致堆栈溢出错误,如果源对象包含循环引用。
3. 什么时候应该使用浅拷贝?
浅拷贝应该用于复制简单对象,例如字符串、数字和布尔值。
4. 什么时候应该使用深拷贝?
深拷贝应该用于复制复杂对象,例如包含嵌套对象或循环引用的对象。
5. 如何检查一个对象是浅拷贝还是深拷贝?
要检查一个对象是浅拷贝还是深拷贝,可以查看更改嵌套对象的属性是否会影响源对象。如果会,则它是浅拷贝;如果不会,则它是深拷贝。