返回

深入理解 JavaScript 中对象的深拷贝与浅拷贝

见解分享

JavaScript 对象的深拷贝与浅拷贝

在 JavaScript 中,理解对象的深拷贝和浅拷贝至关重要,它直接影响着我们对数据的操作方式和数据的安全性。

浅拷贝

浅拷贝只复制对象顶层的属性,而不会复制嵌套对象。当我们修改浅拷贝的属性时,原始对象也会受到影响。这是因为浅拷贝创建了一个新的对象,但它指向原始对象的嵌套对象。

const originalObj = {
  name: 'John Doe',
  address: {
    street: 'Main Street',
    number: 123,
  },
};

const shallowCopy = Object.assign({}, originalObj);

shallowCopy.address.street = 'Oak Street';

console.log(originalObj); // { name: 'John Doe', address: { street: 'Oak Street', number: 123 } }

深拷贝

深拷贝创建一个全新的对象,其中包含原始对象的所有属性和嵌套对象的新副本。修改深拷贝的属性不会影响原始对象。

可以使用递归函数或 JSON.parse(JSON.stringify(obj)) 来实现深拷贝。

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  const newObj = Array.isArray(obj) ? [] : {};

  for (const key in obj) {
    newObj[key] = deepCopy(obj[key]);
  }

  return newObj;
}

const deepCopy = JSON.parse(JSON.stringify(originalObj));

deepCopy.address.street = 'Pine Street';

console.log(originalObj); // { name: 'John Doe', address: { street: 'Main Street', number: 123 } }

区别

浅拷贝:

  • 只复制顶层属性
  • 修改浅拷贝会影响原始对象
  • 速度快,内存占用低

深拷贝:

  • 复制所有属性和嵌套对象
  • 修改深拷贝不会影响原始对象
  • 速度慢,内存占用高

应用场景

浅拷贝:

  • 当我们希望对对象进行轻量级的更改时
  • 当我们不关心嵌套对象的修改时
  • 当我们希望节省内存时

深拷贝:

  • 当我们希望创建原始对象的完全独立副本时
  • 当我们希望防止原始对象被意外修改时
  • 当我们希望在不同的上下文中使用同一对象时

数据类型

不同的数据类型在深拷贝和浅拷贝中的行为也不同。

基本类型:

  • 数值、布尔值、字符串等基本类型在浅拷贝和深拷贝中都是按值传递。
  • 修改基本类型的副本不会影响原始值。

引用类型:

  • 数组、对象等引用类型在浅拷贝中按引用传递。
  • 修改引用类型的副本可能会影响原始对象。
  • 深拷贝创建的是引用类型的副本,因此修改副本不会影响原始对象。

结论

深拷贝和浅拷贝是 JavaScript 中处理对象的重要技术。了解它们的差异和应用场景对于编写安全、健壮的代码至关重要。通过明智地选择正确的拷贝方法,我们可以确保我们的数据得到妥善保护,并且不会出现意外的修改。