返回

深入浅出,剖析 JavaScript 中的深拷贝

前端

在 JavaScript 中,深拷贝与浅拷贝都是克隆对象的方法。然而,这两种方法在实现方式和效果上存在着本质的区别。

浅拷贝

浅拷贝会创建新对象,但仅仅复制原始对象的一层属性,不会复制嵌套对象。也就是说,新对象中对嵌套对象的引用指向与原始对象中相同的对象。

const obj1 = {
  name: 'John',
  address: {
    street: 'Main Street',
    city: 'New York'
  }
};

const obj2 = Object.assign({}, obj1);

obj2.name = 'Jane';
obj2.address.street = 'Park Avenue';

console.log(obj1); // { name: 'John', address: { street: 'Park Avenue', city: 'New York' } }

在上面的示例中,obj1obj2 是两个独立的对象,但它们都引用同一个 address 对象。当我们修改 obj2nameaddress.street 属性时,obj1 也受到了影响,因为它们共享同一个 address 对象。

深拷贝

深拷贝会创建新对象,并复制原始对象的所有属性,包括嵌套对象。这意味着,新对象中对嵌套对象的引用指向的是新创建的对象,而不是原始对象中的对象。

const obj1 = {
  name: 'John',
  address: {
    street: 'Main Street',
    city: 'New York'
  }
};

const obj2 = JSON.parse(JSON.stringify(obj1));

obj2.name = 'Jane';
obj2.address.street = 'Park Avenue';

console.log(obj1); // { name: 'John', address: { street: 'Main Street', city: 'New York' } }

在上面的示例中,obj1obj2 是两个独立的对象,并且它们都具有自己的 address 对象。当我们修改 obj2nameaddress.street 属性时,obj1 不会受到影响,因为它们引用的是不同的 address 对象。

何时使用深拷贝?

深拷贝通常用于以下情况:

  • 当您需要在不影响原始对象的情况下修改对象时。
  • 当您需要将对象传递给另一个函数或模块时。
  • 当您需要将对象存储在数据库或其他持久化存储中时。

何时使用浅拷贝?

浅拷贝通常用于以下情况:

  • 当您需要快速复制对象时。
  • 当您不需要修改对象的属性时。
  • 当您需要将对象作为参数传递给函数或模块时。

实现深拷贝的方法

除了使用 JSON.parse(JSON.stringify()) 方法之外,还可以使用以下方法实现深拷贝:

  • 使用 lodash 库的 _.cloneDeep() 方法。
  • 使用 ramda 库的 R.clone() 方法。
  • 使用 immer 库实现不可变状态管理。

总结

深拷贝和浅拷贝都是 JavaScript 中克隆对象的方法,但在实现方式和效果上存在着本质的区别。深拷贝会创建新对象并复制原始对象的所有属性,包括嵌套对象,而浅拷贝只会创建新对象并复制原始对象的一层属性。深拷贝通常用于需要在不影响原始对象的情况下修改对象的情况,而浅拷贝通常用于需要快速复制对象的情况。