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}
如果只有一個參數,Object.assign
會直接返回該參數。
const obj = {a: 1}; Object.assign(obj) === obj // true
如果該參數不是對象,則會先轉成對象,然后返回。
typeof Object.assign(2) // "object"
由於undefined
和null
無法轉成對象,所以如果它們作為參數,就會報錯。
Object.assign(undefined) // 報錯 Object.assign(null) // 報錯
如果非對象參數出現在源對象的位置(即非首參數),那么處理規則有所不同。首先,這些參數都會轉成對象,如果無法轉成對象,就會跳過。這意味着,如果undefined
和null
不在首參數,就不會報錯。
let obj = {a: 1}; Object.assign(obj, undefined) === obj // true Object.assign(obj, null) === obj // true
其他類型的值(即數值、字符串和布爾值)不在首參數,也不會報錯。但是,除了字符串會以數組形式,拷貝入目標對象,其他值都不會產生效果。
const v1 = 'abc'; const v2 = true; const v3 = 10; const obj = Object.assign({}, v1, v2, v3); console.log(obj); // { "0": "a", "1": "b", "2": "c" }
上面代碼中,v1
、v2
、v3
分別是字符串、布爾值和數值,結果只有字符串合入目標對象(以字符數組的形式),數值和布爾值都會被忽略。這是因為只有字符串的包裝對象,會產生可枚舉屬性。
Object(true) // {[[PrimitiveValue]]: true} Object(10) // {[[PrimitiveValue]]: 10} Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
上面代碼中,布爾值、數值、字符串分別轉成對應的包裝對象,可以看到它們的原始值都在包裝對象的內部屬性[[PrimitiveValue]]
上面,這個屬性是不會被Object.assign
拷貝的。只有字符串的包裝對象,會產生可枚舉的實義屬性,那些屬性則會被拷貝。
Object.assign
拷貝的屬性是有限制的,只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false
)。
Object.assign({b: 'c'}, Object.defineProperty({}, 'invisible', { enumerable: false, value: 'hello' }) ) // { b: 'c' }
上面代碼中,Object.assign
要拷貝的對象只有一個不可枚舉屬性invisible
,這個屬性並沒有被拷貝進去。
屬性名為 Symbol 值的屬性,也會被Object.assign
拷貝。
Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' }) // { a: 'b', Symbol(c): 'd' }
其中關於使用Object.assign()的淺拷貝以及常見用途,見詳情: