返回

浅尝辄止与深度关怀:JS 浅拷贝与深拷贝的博弈

前端

浅显直观的浅拷贝:

浅拷贝,顾名思义,它只会在内存层级,像剥离表层一样,轻松地生成一份新的副本。新的副本中,那些引以为豪的属性,都是对原对象的一个“值”层级上的共用。这就好比孪生双胞胎,看似一模一样,却拥有着不同的个体。

浅拷贝与它的浅显相伴,在诸多场合常常被视作数据拷贝的惯常手段。但仔细审视它的过程,您就会发觉,这种拷贝方式着重于数据第一层的状态,对于嵌套对象,它只会浅尝辄止的保留一个对其的引用的指针。

举个简单的例子,让我们将一个简单的对象,例如:

const person = {
  name: 'John',
  age: 25,
  address: {
    street: '123 Main St.',
    city: 'Anytown',
    state: 'CA',
    zip: '99999'
  }
};

使用 Object.assign(),JavaScript的浅拷贝魔法棒,我们来一个新老对象的换位。

const clone = Object.assign( {}, person );

万事俱备,本以为是时候让双生诞生了,可结果是,新对象的确拥有了一个新指针,但是对于嵌套对象 Address,让我们一层一层的往下看:

clone.address;
// { street: '123 Main St.', city: 'Anytown', state: 'CA', zip: '99999' }

两个对象的地址属性指向的是一个相同的引用!这也就意味着,两个对象在地址层面上的改变,都将会同步生效。

深谋远虑的深拷贝:

倘若对比浅拷贝的漫不经心,深拷贝则显现出深谋远虑。

它需要跋山涉水,去构建一个彻彻底新的对象。这种耗时耗工,方可构建出的新对象,足以告慰,它在内存上的新家,确是一个全新的堆内存地。

JSON.parse(JSON.stringify()),凭借它 JSON 的深度洞察力,便可为我们轻松实现这种翻山越岭。

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

再度审视我们的 Address 属性,此番故地重游,已经重归原样:

deepCopy.address;
// { street: '123 Main St.', city: 'Anytown', state: 'CA', zip: '99999' }

知晓其乐,善用其道:

浅拷贝与深拷贝,两个泾渭分明的存在,各显其能。

浅拷贝的快速与轻松,深拷贝的严谨与周全,皆可根据不同的用例,发挥妙手偶得之能。

因此,熟知并巧妙的善用各自的特点,是每个 JavaScript 开发者所必备的利器。