返回

你不会的JS深浅拷贝,面试必挂!

前端

浅拷贝与深拷贝:深入理解 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. 如何检查一个对象是浅拷贝还是深拷贝?
要检查一个对象是浅拷贝还是深拷贝,可以查看更改嵌套对象的属性是否会影响源对象。如果会,则它是浅拷贝;如果不会,则它是深拷贝。