在开发前端应用时,我们经常需要对对象进行深拷贝。在 ECMAScript 2016 中,我们可以使用 Object.assign 方法来实现对象深拷贝。本文将详细介绍如何使用 Object.assign 方法实现对象深拷贝,并提供示例代码。
什么是对象深拷贝
对象深拷贝是指将一个对象复制到另一个对象中,而且不共享同一引用。这意味着在复制后的对象上修改属性值不会影响原始对象。
常见的对象拷贝方式
在 ECMAScript 2016 之前,我们通常使用以下方式进行对象拷贝:
1. for...in 循环
使用 for...in 循环遍历源对象,将每个属性复制到目标对象中。
// javascriptcn.com 代码示例 function deepCopy(target, source) { for (let key in source) { if (typeof source[key] === 'object') { target[key] = Array.isArray(source[key]) ? [] : {}; deepCopy(target[key], source[key]); } else { target[key] = source[key]; } } }
2. JSON.parse + JSON.stringify
将源对象序列化为 JSON 字符串,再将 JSON 字符串反序列化为目标对象。
function deepCopy(target, source) { target = JSON.parse(JSON.stringify(source)); return target; }
以上两种方法都有缺点。第一种方法需要手动递归遍历目标对象的属性,当属性嵌套层数较深时,递归效率低;第二种方法无法拷贝函数和 RegExp 类型,并且性能较低。
Object.assign 方法解决问题
在 ECMAScript 2016 中,Object.assign 提供了更好的解决方案,它可以将多个源对象合并到目标对象中,并返回目标对象。当源对象中的属性是对象时,它会递归地将属性值合并到目标对象中。
使用 Object.assign 方法实现对象深拷贝的示例代码如下:
function deepCopy(target, ...sources) { sources.forEach(source => { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); }); return target; }
以上代码使用了 Object.getOwnPropertyDescriptors 方法。这个方法会返回指定对象的所有自身属性(不可枚举属性也包括在内)的描述符。然后我们可以通过 Object.defineProperties 方法将这些属性描述符应用到目标对象中。
示例代码
以下是使用 Object.assign 方法实现对象深拷贝的示例代码:
// javascriptcn.com 代码示例 const source = { name: 'John', age: 25, address: { city: 'Shenzhen', street: '123 Main Street' } }; const target = {}; deepCopy(target, source); console.log(target); // { name: 'John', age: 25, address: { city: 'Shenzhen', street: '123 Main Street' } } target.address.city = 'Beijing'; console.log(target); // { name: 'John', age: 25, address: { city: 'Beijing', street: '123 Main Street' } } console.log(source); // { name: 'John', age: 25, address: { city: 'Shenzhen', street: '123 Main Street' } }
总结
在 ECMAScript 2016 中,Object.assign 提供了一种简单高效的对象拷贝方式。使用 Object.assign 方法可以轻松实现对象深拷贝,并且克服了其他方式的缺点。尽管在较旧的浏览器版本中不支持 Object.assign 方法,但我们可以使用 polyfill 或者其他实现方式来解决问题。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6534b2327d4982a6eb9bc620