Object.assign
方法用於對象的合並,將源對象(source)的所有可枚舉屬性,復制到目標對象(target)。
const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
Object.assign
方法的第一個參數是目標對象,后面的參數都是源對象。
注意,如果目標對象與源對象有同名屬性,或多個源對象有同名屬性,則后面的屬性會覆蓋前面的屬性。
const target = { a: 1, b: 1 }; const source1 = { b: 2, c: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
注意點
(1)淺拷貝
Object.assign
方法實行的是淺拷貝,而不是深拷貝。也就是說,如果源對象某個屬性的值是對象,那么目標對象拷貝得到的是這個對象的引用。
const obj1 = {a: {b: 1}}; const obj2 = Object.assign({}, obj1); obj1.a.b = 2; obj2.a.b // 2
上面代碼中,源對象obj1
的a
屬性的值是一個對象,Object.assign
拷貝得到的是這個對象的引用。這個對象的任何變化,都會反映到目標對象上面。
(2)同名屬性的替換
對於這種嵌套的對象,一旦遇到同名屬性,Object.assign
的處理方法是替換,而不是添加。
const target = { a: { b: 'c', d: 'e' } } const source = { a: { b: 'hello' } } Object.assign(target, source) // { a: { b: 'hello' } }
上面代碼中,target
對象的a
屬性被source
對象的a
屬性整個替換掉了,而不會得到{ a: { b: 'hello', d: 'e' } }
的結果。這通常不是開發者想要的,需要特別小心。
一些函數庫提供 Object.assign
的定制版本(比如 Lodash 的_.defaultsDeep
方法),可以得到深拷貝的合並。
(3)數組的處理
Object.assign
可以用來處理數組,但是會把數組視為對象。
Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3]
上面代碼中,Object.assign
把數組視為屬性名為 0、1、2 的對象,因此源數組的 0 號屬性4
覆蓋了目標數組的 0 號屬性1
。
(4)取值函數的處理
Object.assign
只能進行值的復制,如果要復制的值是一個取值函數,那么將求值后再復制。
const source = { get foo() { return 1 } }; const target = {}; Object.assign(target, source) // { foo: 1 }
上面代碼中, source
對象的foo
屬性是一個取值函數,Object.assign
不會復制這個取值函數,只會拿到值以后,將這個值復制過去。