在前端开发中,我们经常遇到需要对复杂数据类型进行复制的情况,例如对象和数组。然而,由于 JavaScript 中的对象和数组都是引用类型,所以直接进行复制实际上只是复制了一个指向原始数据的引用,这就容易导致在修改复制后的数据时影响到原始数据,进而出现各种问题。
为了解决这个问题,ES12 中新增了一些新特性,可以更方便地进行对象和数组的深拷贝和展开复制。
解决方案
Object.create()
Object.create() 是一个用于创建新对象的方法,其可以接收一个原型对象作为参数,并创建出一个新对象,该新对象的原型指向给定原型对象。
-- -------------------- ---- ------- --- ---- - - ----- ------- ---- --- -------- ----------- ------------- - --- ---- - ------------------- ---------------------- -- ---- --------------------- -- -- ------------------------- -- ----------- -------------
在这个例子中,我们使用 Object.create() 方法创建了一个新对象 obj2,其原型对象指向 obj1。我们可以看到,obj2 继承了 obj1 中的属性和方法。
Object.assign()
Object.assign() 方法可以将一个或多个源对象的属性和方法复制到目标对象中,并返回目标对象。
let obj1 = { name: 'Jack', age: 20 } let obj2 = { hobbies: ['reading', 'travelling'] } let newObj = Object.assign({}, obj1, obj2) console.log(newObj) // { name: "Jack", age: 20, hobbies: ["reading", "travelling"] }
在这个例子中,我们创建了两个对象 obj1 和 obj2,使用 Object.assign() 方法将它们合并成了一个新对象 newObj。
需要注意的是,Object.assign() 方法只是进行了浅拷贝,如果源对象中的属性值是引用类型,只会复制其引用而不是值,因此在修改 newObj 中的 hobbies 数组时,会影响到 obj2 中的 hobbies 数组。
Spread Operator
Spread Operator 也称为展开操作符,可以展开数组和对象,将其复制到另一个数组或对象中。
let arr1 = [1, 2, 3] let arr2 = [...arr1] // 等同于 let arr2 = [1, 2, 3] console.log(arr2) // [1, 2, 3] console.log(arr2 === arr1) // false
在这个例子中,我们使用 Spread Operator 将数组 arr1 的值展开到了一个新数组 arr2 中,这样就可以对 arr2 进行修改而不会影响到 arr1。
let obj1 = { name: 'Jack', age: 20, hobbies: ['reading', 'travelling'] } let obj2 = { ...obj1 } console.log(obj2) // { name: "Jack", age: 20, hobbies: ["reading", "travelling"] } console.log(obj2 === obj1) // false
在这个例子中,我们使用 Spread Operator 将对象 obj1 中的属性和方法展开到了一个新对象 obj2 中,这样就可以对 obj2 进行修改而不会影响到 obj1。
需要注意的是,Spread Operator 也只是进行了浅拷贝,如果对象中的属性值是引用类型,只会复制其引用而不是值。
总结
ES12 中新增的解决方案可以更方便地进行对象和数组的深拷贝和展开复制,避免了因引用类型副本容易出现的问题。需要根据实际情况选择适合的方法来复制数据类型。
另外,以上介绍的方法均为浅拷贝,如果需要进行深拷贝可以使用第三方库,例如 lodash 的 cloneDeep() 方法。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64a0229d48841e9894c7d713