1. Object.assign()
Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象分配到目標(biāo)對象鹏秋。它將返回目標(biāo)對象。
語法: Object.assign(target, ...sources)
參數(shù):
- target: 目標(biāo)對象招驴。
- sources: 源對象痊臭。
返回值: 目標(biāo)對象
const target = { a: 1, b: 2 }
const source = { b: 4, c: 5 }
const returnedTarget = Object.assign(target, source)
target // { a: 1, b: 4, c: 5 }
returnedTarget // { a: 1, b: 4, c: 5 }
如果只有一個參數(shù),Object.assign會直接返回該參數(shù)雅倒。
const obj = {a: 1}
Object.assign(obj) // {a: 1}
Object.assign(obj) === obj // true
如果該參數(shù)不是對象嫁佳,則會先轉(zhuǎn)成對象挨队,然后返回。
typeof Object.assign(2) // "object"
由于undefined和null無法轉(zhuǎn)成對象蒿往,所以如果它們作為參數(shù)盛垦,就會報錯。
Object.assign(undefined) // 報錯
Object.assign(null) // 報錯
注意點(diǎn):
(1)淺拷貝
Object.assign方法實行的是淺拷貝瓤漏,而不是深拷貝腾夯。也就是說,如果源對象某個屬性的值是對象蔬充,那么目標(biāo)對象拷貝得到的是這個對象的引用俯在。
const obj1 = {a: {b: 1}}
const obj2 = Object.assign({}, obj1)
obj1.a.b = 2
obj2.a.b // 2
復(fù)制代碼上面代碼中,源對象obj1的a屬性的值是一個對象娃惯,Object.assign拷貝得到的是這個對象的引用。這個對象的任何變化肥败,都會反映到目標(biāo)對象上面趾浅。
(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' } }
的結(jié)果如输。這通常不是開發(fā)者想要的,需要特別小心央勒。
一些函數(shù)庫提供 Object.assign
的定制版本(比如 Lodash
的_.defaultsDeep
方法)不见,可以得到深拷貝的合并。
(3)數(shù)組的處理 Object.assign
可以用來處理數(shù)組崔步,但是會把數(shù)組視為對象稳吮。
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
上面代碼中,Object.assign
把數(shù)組視為屬性名為 0井濒、1灶似、2
的對象,因此源數(shù)組的 0
號屬性4
覆蓋了目標(biāo)數(shù)組的 0
號屬性1
瑞你。
(4)取值函數(shù)的處理
Object.assign
只能進(jìn)行值的復(fù)制酪惭,如果要復(fù)制的值是一個取值函數(shù),那么將求值后再復(fù)制者甲。
const source = {
get foo() { return 1 }
}
const target = {}
Object.assign(target, source)
// { foo: 1 }
上面代碼中春感, source
對象的foo
屬性是一個取值函數(shù),Object.assign
不會復(fù)制這個取值函數(shù)过牙,只會拿到值以后甥厦,將這個值復(fù)制過去。
用法
Object.assign
方法有很多用處寇钉。
(1)為對象添加屬性
class Point {
constructor(x, y) {
Object.assign(this, {x, y})
}
}
上面方法通過Object.assign
方法刀疙,將x
屬性和y
屬性添加到Point
類的對象實例。
(2)為對象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
})
// 等同于下面的寫法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
}
SomeClass.prototype.anotherMethod = function () {
···
}
上面代碼使用了對象屬性的簡潔表示法扫倡,直接將兩個函數(shù)放在大括號中谦秧,再使用assign
方法添加到SomeClass.prototype
之中。
(3)克隆對象
function clone(origin) {
return Object.assign({}, origin)
}
上面代碼將原始對象拷貝到一個空對象撵溃,就得到了原始對象的克隆疚鲤。
不過,采用這種方法克隆缘挑,只能克隆原始對象自身的值集歇,不能克隆它繼承的值。如果想要保持繼承鏈语淘,可以采用下面的代碼诲宇。
function clone(origin) {
let originProto = Object.getPrototypeOf(origin)
return Object.assign(Object.create(originProto), origin)
}
(4)合并多個對象
將多個對象合并到某個對象际歼。
const merge = (target, ...sources) => Object.assign(target, ...sources)
如果希望合并后返回一個新對象,可以改寫上面函數(shù)姑蓝,對一個空對象合并鹅心。
const merge = (...sources) => Object.assign({}, ...sources)
2. Object.keys()、Object.value()纺荧、Object.entries()
(1)Object.keys() 返回一個包含該對象所有的鍵的數(shù)組旭愧。
用法
let user = {
name: 'IU',
age: 18
}
const keyList = Object.keys(user)
console.log(keyList) // ["name", "age"]
// 可以使用 Array.prototype.includes() 方法檢查數(shù)組中是否存在鍵。
const val = 'age'
if (keyList.length > 0) {
if(keyList.includes(val)){
console.log('存在 key')
} else {
console.log('不存在 key')
}
}
// 計算屬性數(shù)量
const count = (obj) => Object.keys(obj).length
count(user) // 2
(2)Object.values(obj) 返回一個包含該對象所有的值的數(shù)組宙暇。
let user = {
name: 'IU',
age: 18
}
// 遍歷所有的值
for (let value of Object.values(user)) {
console.log(value)
}
// IU
// 18
用法
屬性求和
let price = {
HTML: 99,
JavaScript: 299,
CSS: 199
}
方式一:使用 Object.values 和 for..of 循環(huán)返回所有數(shù)的總和
const sumPrice = (val) => {
let sum = 0
for (let salary of Object.values(val)) {
sum += salary
}
return sum
}
sumPrice(price) // 650
方式二:使用 Object.values 和 reduce 來求和
const sumPrice = (val) => Object.values(val).reduce((a, b) => a + b, 0)
sumPrice(price) // 650
(3)Object.entries(obj) 返回一個包含該對象所有 [key, value] 鍵值對的數(shù)組输枯。
let user = {
name: 'IU',
age: 18
}
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`)
}
// name: IU
// age: 18
注意
Object.keys/values/entries
方法都是用Object.
來調(diào)用。Object.keys/values/entries
會忽略symbol
屬性就像
for..in
循環(huán)一樣客给,這些方法會忽略使用Symbol(...)
作為鍵的屬性用押。
如果我們想要Symbol
類型的鍵,可以Object.getOwnPropertySymbols()
方法 靶剑,它會返回一個只包含 Symbol 類型的鍵的數(shù)組蜻拨。另外,還有一種方法Reflect.ownKeys(obj)
桩引,它會返回所有鍵缎讼。
3. Object.defineProperty()
Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現(xiàn)有屬性坑匠,并返回此對象血崭。
語法: Object.defineProperty(obj, prop, descriptor)
參數(shù)
- obj: 要定義屬性的對象。
- prop: 要定義或修改的屬性的名稱或 Symbol 厘灼。
- descriptor: 要定義或修改的屬性描述符夹纫。
具體用法可以參照Vue雙向綁定原理
這一部分,這里有對該方法的詳細(xì)介紹设凹。