前言
在JavaScript
中耿币,幾乎每一個(gè)值都是某種特定的類型對象制圈,Es6
也著重提升了對象的功能性睹酌,Es6
通過多種方式來加強(qiáng)對象的使用邓尤,通過簡單的語法擴(kuò)展佑菩,提供更多操作對象及與對象交互的方法。下面來介紹它們裁赠。
對象字面量語法擴(kuò)展
對象字面量如此就行殿漠,就是我們想創(chuàng)建對象,不在需要編寫冗余的代碼佩捞。直接通過的它的簡潔語法就可以實(shí)現(xiàn)绞幌。那么看看Es6為對象做了那些特性吧。
屬性初始值的簡寫
在Es5中一忱,對象字面量只是簡單的鍵值和集合莲蜘,這意味著初始化屬性有一些重復(fù)。
function person(name) {
return {
name: name
}
}
在Es6中帘营,通過屬性的簡寫則可以省去這name
屬性一遍票渠,當(dāng)一個(gè)對象的屬性和變量同名時(shí),則可以省去冒號和值芬迄∥是辏看如下案例
function person(name) {
return {
name
}
}
對象方法的簡寫語法
Es6也改進(jìn)了對象字面量的對象簡寫方法,在Es5中禀梳,定義對象方法必須的得寫完整名稱才可以杜窄。
Es5案例
let person = {
test: function() {}
}
Es6案例
let person() {
test() {}
}
通過Es6對象的方法簡寫,定義的是一個(gè)匿名表達(dá)式算途,這個(gè)函數(shù)擁有和Es5一模一樣的特性塞耕。Es5定義對象函數(shù)和Es6簡寫定義的函數(shù)唯一區(qū)別,簡寫的函數(shù)可以使用super
嘴瓤。
可計(jì)算屬性名
在Es5中扫外,如果想要通過計(jì)算得到屬性名莉钙,則需要用[]
方括號代替。
let person = {}
let value = "hello WaRen"
person["wa ren"] = "蛙人"
person[value] = "value"
上面example中筛谚,是我們在es5中的做法胆胰,如果對象的key值是一個(gè)變量,那我們就使用對象方括號添加刻获。
在Es6中,可在對象字面量中使用可計(jì)算屬性名稱瞎嬉,我們來看下面例子
let key = "name"
let person = {
[key]: "蛙人" // 在對象字面量中這樣使用[]方括號定義key是Es6語法
[`${key}_test`]: "test"
}
上面這種在對象字面量中使用方括號表示該屬性名是可以計(jì)算的蝎毡,可以寫表達(dá)式的,然后最終key值都會以字符串類型返回氧枣。切記沐兵,在對象字面量中使用方括號[]定義key值是Es6中的語法
。本人也是剛知道(基礎(chǔ)不扎實(shí) 嗚嗚嗚)便监,經(jīng)測試bable轉(zhuǎn)換Es6轉(zhuǎn)Es5可以看到結(jié)果扎谎。
重復(fù)的對象字面量屬性
在Es5嚴(yán)格模式下加入了對象字面量重復(fù)屬性的驗(yàn)證,當(dāng)同時(shí)存在多個(gè)同名屬性時(shí)會拋出異常烧董』侔校看下面例子
"use strict"
var person = {
name: "蛙人",
name: "張三" // 在Es5嚴(yán)格模式下會拋出語法錯(cuò)誤
}
在Es5嚴(yán)格模式下時(shí),第二個(gè)屬性name
會觸發(fā)一個(gè)語法錯(cuò)誤逊移,但是在Es6中重復(fù)屬性檢查被移除了预吆,Es6中無論是在嚴(yán)格模式下,還是不在嚴(yán)格模式下代碼都不會進(jìn)行重復(fù)屬性驗(yàn)證胳泉,對于重復(fù)屬性都是后面的覆蓋前面的拐叉。ps: 這個(gè)我也是剛剛知道 流下了沒技術(shù)的眼淚 。扇商。凤瘦。
"use strict"
let person = {
name: "蛙人",
name: "張三"
}
在上面example中,我們可以看到案铺,這是Es6標(biāo)準(zhǔn)重復(fù)屬性并沒有拋出異常而是后面對象覆蓋前面對象蔬芥,最后name
屬性為"張三",我們現(xiàn)在瀏覽器運(yùn)行的都是Es6標(biāo)準(zhǔn)控汉。
Es6對象新增的方法
Es6中在全局Object
對象上引入了一些新方法坝茎。
Object.is
我們在Es5中的時(shí)候經(jīng)常使用==
相等運(yùn)算符 or ===
全等運(yùn)算符來比較值,然而在Es5中相等運(yùn)算符或者全等運(yùn)算符也不完全準(zhǔn)確暇番,這里拿官網(wǎng)說的舉個(gè)例子嗤放,+0和-0
這個(gè)在JavaScript
引擎中被表示兩個(gè)不同的實(shí)體,而使用全等運(yùn)算符或者相等運(yùn)算符都會返回ture
, 同樣NaN == NaN
返回false壁酬。然而Es6中出現(xiàn)了Object.is
方法來彌補(bǔ)這些不足次酌,Object.is
方法接收2個(gè)參數(shù)恨课,如果這兩個(gè)參數(shù)值相等并且類型也相等,則返回true
console.log(+0 == -0) // ture
console.log(+0 === -0) // true
console.log(Object.is(+0, -0)) // false
console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(Object.is(NaN, NaN)) // true
console.log(10 == "10") // true
console.log(10 === "10") // false
console.log(Object.is(10, "10")) // false
上面example中岳服,我們可以看到Object.is
方法是挺嚴(yán)格的剂公,但是這個(gè)只是處理特殊情況下使用,所以我們沒必要拋棄==
or ===
吊宋。
Object.assign
Object.assign方法可以接收任意數(shù)量源對象纲辽,第一個(gè)參數(shù)是接收者,也就是最終的返回值璃搜,第二個(gè)參數(shù)以后都是會復(fù)制到第一個(gè)參數(shù)里面拖吼,所以如果有多個(gè)源對象具有同名屬性key
值,那么則靠后的對象會覆蓋靠前的對象这吻。來看下面例子
let test1 = {
name: "蛙人"
}
let test2 = {
name: "張三"
}
let result = Object.assign({}, test1, test2)
console.log(result) // {name: "張三"}
上面example中吊档,可以看到上面的對象屬性如果具有同名的,后面的則會覆蓋前面的唾糯。如果參數(shù)里傳入的是非對象也能執(zhí)行怠硼,只不過會忽略。來看下面例子
let result = Object.assign({}, 1, 2, 3)
console.log(result) // {}
注意: Object.assign方法不能將取值函數(shù)(訪問器屬性)復(fù)制到對象中移怯,由于Object.assign方法執(zhí)行了賦值操作香璃,那么對象最終會轉(zhuǎn)換成一個(gè)普通的屬性。
let test = {
get name() {
return "蛙人"
}
}
let result = Object.assign({}, test)
console.log(Object.getOwnPropertyDescriptor(result, "name")) // {configurable: true enumerable: true value: "蛙人" writable: true}
上面example中舟误,可以看到我們復(fù)制對象的最終結(jié)果增显,取值函數(shù)確實(shí)丟失了,我們可以根據(jù)獲取對象的描述屬性
可以看到脐帝。如果不懂對象的描述屬性
可以看我這篇文章《深入理解JavaScript對象》
Object.setPrototypeOf
在Es5中同云,提供了Object.getPrototypeOf
方法獲取對象的原型,然而Es5中并沒有提供設(shè)置對象的原型的方法堵腹,如果我們想要設(shè)置對象的原型炸站,xx.__proto__ = xx.__proto__
顯然這樣寫也是沒問題的,但是并不合理疚顷。所以Es6提供了Object.setPrototypeOf
方法, 這個(gè)方法接收兩個(gè)參數(shù)旱易,第一個(gè)就是被修改的對象,第二個(gè)是原型對象腿堤。來看下面例子
let person = {}
function Fn() {}
let fn = new Fn()
Object.setPrototypeOf(person, fn)
console.log(person)
上面example中阀坏,可以看到就是把person
的原型對象修改成fn
的原型對象,這時(shí)你在訪問person
對象就可以清楚的看到原型對象已經(jīng)被更改了笆檀。
Object.values
Object.values
方法返回一個(gè)數(shù)組忌堂,成員是參數(shù)對象自身的,不包含繼承和原型上的
let person = {
name: "蛙人",
age: 24,
sex: "male"
}
console.log(Object.values(person)) // ["蛙人", 24, "male"]
Object.entries
Object.entries
方法返回一個(gè)數(shù)組(也就是一個(gè)二維數(shù)組)酗洒,成員是參數(shù)對象自身的士修,屬性的鍵值對數(shù)組枷遂,不包含繼承和原型上的。
let person = {
name: "蛙人",
age: 24,
sex: "male"
}
console.log(Object.entries(person)) // [["name", "蛙人"], ["age", 24], ["sex", "male"]]
Object.fromEntries
Object.fromEntries
是Object.entries
的反向操作棋嘲,返回值是一個(gè)對象酒唉,用于將一個(gè)鍵值對數(shù)組轉(zhuǎn)為對象。
let testArr = [
["name", "蛙人"],
["age", 24],
["sex", "male"]
]
console.log(Object.fromEntries(testArr)) // {name: "蛙人", age: 24, sex: "male"}
自有對象屬性枚舉順序
在Es5中沒有定義對象屬性的枚舉順序沸移,是由js引擎廠商自行決定的痪伦。然而,在Es6中規(guī)定了對象自有屬性被枚舉返回的順序雹锣。自有屬性枚舉順序的基本規(guī)則如下:
- 所有數(shù)字鍵按升序排序
- 所有字符串鍵按加入對象的順序排序
- 所有symbol鍵按加入對象的順序排序
let o = {
4: 4,
1: 1,
b: "b",
a: "a"
}
o.c = "c"
console.log(Object.keys(o)) // ["1", "4", "b", "a", "c"]
console.log(Object.getOwnPropertyNames(o)) // ["1", "4", "b", "a", "c"]
for (let i in o) {
console.log(i) // 1 4 b a c
}
上面example中网沾,可以看到對象枚舉屬性都是根據(jù)Es6中規(guī)則順序來返回的,請注意 ,對于數(shù)字鍵笆制,盡管在對象字面量中順序是隨意的
,但是在枚舉時(shí)會被重新組合和排序涣达。字符串緊跟數(shù)字鍵后面在辆,并按照該屬性在對象里的順序返回,最后是動態(tài)添加字符串健值度苔。
簡化原型訪問的Super引用
在Es6中匆篓,新提供了super
關(guān)鍵字,該方法是為了簡化獲取當(dāng)前的原型的對象使用的寇窑。來看下面例子
Es5案例
let person = {
getName() {
return Object.getPrototypeOf(this).getVal.call(this)
}
}
let o = {
getVal() {
return "蛙人"
}
}
Object.setPrototypeOf(person, o)
console.log(person.getName()) // 蛙人
上面example中鸦概,可以看到先把person
的原型設(shè)置為o
對象,然后調(diào)用person
對象時(shí)甩骏,該getName
方法里又獲取了當(dāng)前的原型窗市,調(diào)用原型上的方法,也就是調(diào)用的o
對象的方法饮笛。
Es6案例
let person = {
getName() {
return super.getVal.call(this)
}
}
let o = {
getVal() {
return "蛙人"
}
}
Object.setPrototypeOf(person, o)
console.log(person.getName()) // 蛙人
上面example中咨察,可以看到我們把上面代碼稍微調(diào)整了一下,把Object.getPrototypeOf
換成了super
關(guān)鍵字福青。super
關(guān)鍵字作用就是可以代替Object.getPrototypeOf
方法訪問對象原型摄狱。但是super
關(guān)鍵字也是有個(gè)弊端就是只能在對象字面量的方法簡寫情況下使用。來看下面案例
let person = {
getName: function() {
return super.toString() // 報(bào)錯(cuò)
}
}
在上面example中无午,person
對象里用匿名function
定義了一個(gè)屬性媒役,由于在當(dāng)前上下文中super
引用是非法的,所以就拋出錯(cuò)誤宪迟。那么為什么同樣都是函數(shù)而有差異呢酣衷,那么我們繼續(xù)往下看。
正確區(qū)分方法的定義
在Es6之前沒有規(guī)定的方法
這個(gè)概念次泽,方法僅僅是一個(gè)具有功能而非對象的屬性鸥诽,而在Es6中正式將方法定義為一個(gè)函數(shù)商玫,它會有一個(gè)內(nèi)部的[[HomeObject]]
屬性來容納這個(gè)方法從屬的對象∧到瑁看下面例子
let person = {
getName() {} // 是方法
}
function getName() {} // 不是方法
上面example中拳昌,定義person
對象,它有一個(gè)getName
方法钠龙,由于直接把函數(shù)賦值給了person
對象炬藤,getName
方法的[[HomeObject]]
屬性值為person
對象。然后在看下面用function
關(guān)鍵字定義的getName
方法碴里,這時(shí)它沒有賦值給一個(gè)對象沈矿,所以沒有明確定義[[HomeObject]]
屬性。如果不使用super
關(guān)鍵字這兩個(gè)函數(shù)這點(diǎn)小區(qū)別沒什么大問題咬腋。但是要使用super
關(guān)鍵字的話就尤其重要羹膳。
因?yàn)?code>super關(guān)鍵字引用都通過[[HomeObject]]
屬性來確定后續(xù)運(yùn)行過程。super
關(guān)鍵字先會在[[HomeObject]]
屬性上找到當(dāng)前對象(屬性值)根竿,也就是person
然后在調(diào)用Object.getPrototypeOf
方法獲取當(dāng)前原型陵像, 然后在去原型上找到當(dāng)前同名函數(shù),最后設(shè)置this
綁定并且調(diào)用寇壳。這也就是上面為什么super
關(guān)鍵字會報(bào)錯(cuò)的原因醒颖。
覺得寫的不錯(cuò)的話那就點(diǎn)個(gè)贊叭!
大家也可以加我的微信一起交流 這里