引言
在日常的前端开发中,我们经常会遇到需要将一个对象进行深度拷贝的情况。一般情况下,我们使用常规的方法进行拷贝,比如使用 Object.assign()
或者使用 JSON.parse(JSON.stringify(obj))
。这些方法虽然能够实现浅拷贝或深拷贝的功能,但对于一些复杂的对象,可能会存在一些问题,比如拷贝后的对象和原对象引用了同一个对象引用,修改其中一个对象的属性会影响到另一个对象,这就会导致一些不可预知的问题。
在 ES12 中,新增了一个 Object.getOwnPropertyDescriptors()
方法,该方法能够返回对象自身属性的描述符,包括 value
、 writable
、enumerable
和 configurable
。那么,本文将介绍如何使用该方法来实现对象的深度拷贝。
深度拷贝对象的问题
在深度拷贝对象时,往往会出现对象引用相同的情况。例如,下面代码创建了一个对象 person1
:
const person1 = { name: 'Tom', age: 20, address: { city: 'Beijing', street: 'Changping Road' } };
现在我们想要通过深度拷贝的方式来创建一个对象 person2
,并修改其中一个对象的属性值:
const person2 = JSON.parse(JSON.stringify(person1)); person2.address.city = 'Shanghai';
这时,我们会发现 person1
的 address.city
也被修改了,这就是因为两个对象的 address
属性引用同一个对象引用的缘故。这时候,我们可能需要使用赋值运算符或者 Object.assign()
来解决该问题。
但是使用这些方法时,我们又会发现它们只能实现浅拷贝,即只能拷贝对象自身的属性,而不能拷贝对象的嵌套属性。
使用 Object.getOwnPropertyDescriptors 进行深度拷贝
在 ES12 中,新增了一个 Object.getOwnPropertyDescriptors
方法,该方法能够返回对象自身属性的描述符,包括 value
、 writable
、enumerable
和 configurable
。我们可以利用这个方法,来实现对对象进行深度拷贝。
下面是一个使用 Object.getOwnPropertyDescriptors()
方法深度拷贝对象的示例:
-- -------------------- ---- ------- -------- ------------- - ----- ------ - --- ---------------------------- -- - ----- ---------- - ------------------------------------ ----- -- ----------------- --- ---- -- ------ ---------------- --- --------- - ---------------- - --------------------------- - ----------------------------- ---- ------------ --- ------ ------- -
上面的代码中,我们首先定义了一个 deepCopy
函数,该函数接收一个对象作为参数。函数内部使用 Object.keys()
方法获取对象自身的全部属性,然后使用 Object.getOwnPropertyDescriptor()
方法获取每个属性的描述符。这里使用了一个递归的方式,来对属性值为对象的属性进行拷贝。
一个比较复杂的示例:
-- -------------------- ---- ------- ----- ---- - - ------ ----------- -------- ------- --------- -- ------- ------ ------ --------- - - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- - -- ---------- - ----- ---------- -------- - ----- ----- ------- ------- - - -- ----- ------- - --------------- ------------------------- - --- ------------------------------ - ----- ----------------- ---------
输出的结果:
-- -------------------- ---- ------- - ------ ----------- -------- ------- --------- -- ------- ------ ------ --------- - - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- - -- ---------- - ----- ---------- -------- - ----- ----- ------- ------- - - - - ------ ----------- -------- ------- --------- -- ------- ------ ------ --------- - - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- -- - ------ ------ ------ -- - -- ---------- - ----- ---------- -------- - ----- ----- ------- ------- - - -
从输出结果可以看到,newBook
和 book
的属性值已经完全独立了。
结论
使用 Object.getOwnPropertyDescriptors()
方法能够实现对对象的深度拷贝,避免了一些对象引用同一个对象引用的问题。这种方法的优点是能够拷贝对象自身的所有属性,以及嵌套属性的值。对于一些较为复杂的对象,这种方法更为有效。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/674845ba93696b0268ee40b7