在 JavaScript 中,对象是通过引用来传递的,这意味着当你把一个对象赋值给另一个变量时,它们实际上共享同一个内存地址。这种引用类型的特性在某些情况下是非常有用的,但在其他情况下它可能会导致一些问题,比如深浅拷贝问题。
浅拷贝与深拷贝
浅拷贝指的是创建一个新对象,这个新对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝则是在拷贝对象的同时,也会拷贝对象所引用的所有对象,以及引用对象所引用的对象,直到所有的基本类型都被拷贝完毕。这种方式创建的新对象和原来的对象没有任何关系,因此对其中一个对象的修改不会影响到另一个对象。
解决深浅拷贝问题的方法
在 ECMAScript 2017 中,引入了一种新的方式来解决深浅拷贝问题,那就是使用 Object 的方法 Object.assign() 和 Object.getOwnPropertyDescriptors()。
Object.assign()
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。它接受任意数量的参数,第一个参数为目标对象,后面的参数为源对象。
当目标对象和源对象有相同的属性时,后面的源对象会覆盖前面的源对象。这个方法只会拷贝源对象自身的属性,不会拷贝继承的属性。
浅拷贝
const obj1 = { a: 1 }; const obj2 = { b: 2 }; const obj3 = { c: 3 }; const obj = Object.assign({}, obj1, obj2, obj3); console.log(obj); // {a: 1, b: 2, c: 3}
深拷贝
const obj1 = { a: 1, b: { c: 2 } }; const obj2 = JSON.parse(JSON.stringify(obj1)); console.log(obj2); // {a: 1, b: { c: 2 }}
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors() 方法返回指定对象所有自身属性(非继承属性)的描述对象。每个描述对象都有两个属性:value 和 writable,这两个属性用来表示属性值和可写性。
浅拷贝
const obj1 = { a: 1 }; const obj2 = Object.create(obj1, { b: { value: 2 } }); const obj = Object.assign({}, obj2, Object.getOwnPropertyDescriptors(obj2)); console.log(obj); // { b: 2 }
深拷贝
const obj1 = { a: 1, b: { c: 2 } }; const obj2 = Object.assign({}, obj1, { b: Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj1.b)), }); console.log(obj2); // { a: 1, b: { c: 2 } }
总结
在 ECMAScript 2017 中,通过 Object.assign() 和 Object.getOwnPropertyDescriptors() 方法可以解决 JavaScript 中的深浅拷贝问题。使用这两个方法可以方便地实现浅拷贝和深拷贝,从而避免由于对象引用导致的问题。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/650956f695b1f8cacd412408