瞎說系列之Object.assign入門
前言
過去的一個多月新接手了一個公司的老專案,在實現新需求的同時還需要對有些地方進行重構,故而導致了沒時間更新文章。最近趁著週末更新一篇關於Object.assign使用的文章。
簡介
Object.assign()方法用於將所有可列舉的屬性的值從一個或多個源物件複製到目標物件,它將返回目標物件。這裡有兩點需要注意:1、該方法複製的是可列舉的屬性的值,不可列舉的屬性不會處理。2、它返回的是一個物件。
語法
Object.assign(target,...sources)
基本用法
合併物件
const target = { a: 1 } const source1 = { b: 2 } const source2 = { c: 3 } Object.assign(target, source1, source2) console.log(target) // {a: 1, b: 2, c: 3}
注意:
如果目標物件與源物件的屬性具有相同的鍵,或者多個源物件的屬性具有相同的鍵,則後面物件的屬性會覆蓋前面物件的屬性。
const target = { a: 1, b: 1 } const source1 = { b: 2, c: 2 } const source2 = { c: 3 } Object.assign(target, source1, source2) console.log(target) // {a: 1, b: 2, c: 3}
如果只傳入了一個引數,則該方法會直接返回該引數。
const target = { a: 1 } Object.assign(target) console.log(target) // {a: 1} console.log(Object.assign(target) === target) // true
如果傳入的引數不是物件,原始型別會被包裝為物件。
const target = Object.assign(1) console.log(target) // Number {1} typeof target // "object"
null和undefined無法被轉為物件,所以如果把它們兩個作為目標物件則會報錯。
const target = Object.assign(null) const tar = Object.assign(undefined) // Cannot convert undefined or null to object
如果null和undefined作為源物件,則不會報錯,因為基本資料型別被包裝,null和undefined會被忽略。
const target = Object.assign({a:1}, null) const tar = Object.assign({a:1}, undefined) // {a:1} const target1 = Object.assign(1, null) // Number {1}
如果null和undefined作為源物件中的屬性值,則它們不會被忽略
const target = Object.assign({ a: 1 }, { b: null }, { c: undefined }) console.log(target) // {a: 1, b: null, c: undefined}
拷貝
複製一個物件
const target = Object.assign({}, { a: 1 }) console.log(target) // {a: 1}
拷貝symbol型別的屬性
const target = Object.assign({}, { a: 1 }, { [Symbol('foo')]: 2 }) console.log(target) // {a: 1, Symbol(foo): 2}
拷貝的屬性是有限制的,繼承屬性和不可列舉屬性無法被拷貝。
const obj = Object.defineProperty({}, 'a', { enumerable: false, value: 1 }) console.log(obj) // {a: 1} const target = Object.assign({b: 2}, obj) console.log(target) // {b: 2}
現在把a屬性變成可列舉的屬性。
const obj = Object.defineProperty({}, 'a', { enumerable: true, value: 1 }) console.log(obj) // {a: 1} const target = Object.assign({b: 2}, obj) console.log(target) // {b: 2, a: 1}
接下來再看看基本資料型別的可列舉性。
注意:
首先基本資料型別會被包裝成物件,null和undefined會被忽略。其次只有字串的包裝物件才可能有自身可列舉屬性。
const v1 = "abc" const v2 = true const v3 = 10 const v4 = Symbol("foo") const target = Object.assign({}, v1, null, v2, undefined, v3, v4) console.log(target) // {0: "a", 1: "b", 2: "c"}
拷貝一個數組。該方法會把陣列視為物件,同時在拷貝的時候通過位置來進行覆蓋。
const target = Object.assign([1,2,3],[4,5]) console.log(target) // [4, 5, 3]
深淺拷貝
Object.assgin()實現的是淺拷貝。如果源物件中的某個屬性的值也是物件,那麼目標物件拷貝得到的是這個物件的引用,一旦這個物件發生改變,那麼拷貝後的目標物件也做相應的改變。
let obj1 = { a: 0 , b: { c: 0}} let obj2 = Object.assign({}, obj1) console.log(JSON.stringify(obj2)) // {"a":0,"b":{"c":0}} obj1.a = 1 console.log(JSON.stringify(obj1)) // {"a":1,"b":{"c":0}} console.log(JSON.stringify(obj2)) // {"a":0,"b":{"c":0}} obj2.a = 2 console.log(JSON.stringify(obj1)) // {"a":1,"b":{"c":0}} console.log(JSON.stringify(obj2)) // {"a":2,"b":{"c":0}} obj1.b.c = 3 console.log(JSON.stringify(obj1)) // {"a":1,"b":{"c":3}} console.log(JSON.stringify(obj2)) // {"a":0,"b":{"c":3}}
至於深淺拷貝的區別以及如何實現的問題,會在之後的文章中詳細說明。
常見用途
為物件新增屬性
class Person { constructor(x, y) { Object.assign(this, {x, y}) } }
為物件新增方法
Object.assign(someClass.prototype, { foo(x, y){ .... } })
合併多個物件
Object.assign(target, ...sources)
複製一個物件
const target = Object.assign({}, { a: 1 }) console.log(target) // {a: 1}
為屬性指定預設值
const DEFAULT_VALUE = { name: 'Joe', age: '27' } function foo(options) { return Object.assign({}, DEFAULT_VALUE, options) }
瀏覽器相容性
最後
感謝各位能夠耐心的讀完,如有錯誤歡迎指正,讓我們一起進步。後續的內容,敬請期待。