返回

JS 深浅复制:认识不同副本属性的影响

前端

在 JavaScript 中,复制对象时存在深浅复制之分。深复制会创建目标对象的完全独立副本,而浅复制只会创建目标对象属性的副本,而属性值本身仍指向原来的引用地址。这两种复制方式在不同的场景下具有不同的应用,因此理解它们之间的区别对于提升代码的健壮性和效率至关重要。

首先,我们来了解一下 instanceof 操作符。instanceof 用于判断一个对象是否属于某个类的实例。在复制对象时,我们可以使用 instanceof 来判断副本是否属于与原对象相同的类。如果属于,则表明副本是深复制的;如果不属于,则表明副本是浅复制的。

接下来,我们来看看扩展运算符(...)。扩展运算符可以将一个数组或对象展开成一系列单独的元素或属性。在复制对象时,我们可以使用扩展运算符来创建副本属性。与浅复制不同,扩展运算符创建的副本属性是独立的,不会指向原来的引用地址。

最后,我们再来看一下 Object.assign() 方法。Object.assign() 方法可以将一个或多个源对象的属性复制到目标对象中。在复制对象时,我们可以使用 Object.assign() 方法来创建副本属性。与浅复制不同,Object.assign() 方法创建的副本属性也是独立的,不会指向原来的引用地址。

下面,我们通过一些示例来比较深复制和浅复制的区别:

// 浅复制示例
const originalObject = {
  name: 'John Doe',
  age: 30,
  address: {
    street: '123 Main Street',
    city: 'Anytown',
    state: 'CA',
    zip: '12345'
  }
};

const shallowCopy = {...originalObject};

// 修改浅副本的属性值
shallowCopy.name = 'Jane Doe';
shallowCopy.address.street = '456 Elm Street';

// 输出原始对象和浅副本
console.log(originalObject);
// { name: 'John Doe', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA', zip: '12345' } }

console.log(shallowCopy);
// { name: 'Jane Doe', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA', zip: '12345' } }

// 深复制示例
const deepCopy = JSON.parse(JSON.stringify(originalObject));

// 修改深副本的属性值
deepCopy.name = 'John Smith';
deepCopy.address.street = '789 Oak Street';

// 输出原始对象和深副本
console.log(originalObject);
// { name: 'John Doe', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA', zip: '12345' } }

console.log(deepCopy);
// { name: 'John Smith', age: 30, address: { street: '789 Oak Street', city: 'Anytown', state: 'CA', zip: '12345' } }

在上面的示例中,浅复制只是复制了原对象的属性值,而深复制则复制了原对象的所有属性,包括属性值和对其他对象的引用。因此,修改浅副本的属性值也会影响到原对象,而修改深副本的属性值则不会影响到原对象。

在实际开发中,我们可以根据不同的需求选择不同的复制方式。如果需要创建完全独立的副本,则可以使用深复制;如果只需要复制对象的部分属性,则可以使用浅复制。