你不知道的JS系列 ( 33 ) - 对象复制
JS 初学者最常见的问题之一就是如何复制一个对象。看起来应该有一个内置的 copy() 方法,实际上比想象中的更复杂,我们无法选择一个默认的复制算法
function anotherFunction(){/** ... */}; var anotherObject = { c: true }; var anotherArray = []; var myObject = { a: 2, b: anotherObject, // 引用,不是复本! c: anotherArray, // 另一个引用 d: anotherFunction } anotherArray.push(anotherObject, myObject);
如何准确的表示 myObject 的复制呢?
对于深复制来说,除了复制 myObject 以外还会复制 anotherObject 和 anotherArray。这时问题来了,anotherArray 引用了 anotherObject 和 myObject,所以又要复制 myObject,这时就会由于循环引用导致死循环。
对于 JSON 安全的对象来说(很明显上面的 demo 是不安全的),有一种巧妙的复制方法
var newObj = JSON.parse( JSON.stringify( someObj ) );
这种方法需要保证对象是 JSON 安全的,所以只适用于部分情况。
相比深复制,浅复制非常易懂并且问题很少。ES6 定义了 Object.assign(..) 方法来实现浅复制。第一个参数是目标对象,之后可以跟一个或多个源对象。它会遍历一个或多个源对象的所有可枚举的自有键,并把它们复制到目标对象,最后返回目标对象,就像这样:
var newObj = Object.assign({}, myObject); newObj.a; // 2 newObj.b === anotherObject; // true newObj.c === anotherArray; // true newObj.d === anotherFunction; // true
Object.assign(..) 就是使用 = 操作符复制,所以对源对象属性对一些特性不会被复制到目标对象