瞎說系列之Object.assign入門

軒少發表於2019-03-24

瞎說系列之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)
}
複製程式碼

瀏覽器相容性

瞎說系列之Object.assign入門

最後

感謝各位能夠耐心的讀完,如有錯誤歡迎指正,讓我們一起進步。後續的內容,敬請期待。

相關文章