譯者按: 本文系統(tǒng)地總結(jié)了所有的新特性,并用淺顯的例子解釋。
為了保證可讀性,本文采用意譯而非直譯。另外,本文版權(quán)歸原作者所有,翻譯僅用于學(xué)習(xí)。
一直保持對(duì)JavaScript新特性的關(guān)注是一件很難的事情,特別是還找不到幾個(gè)有用的例子去理解它。
本文會(huì)輔以有用的例子來(lái)講述TC39中的18個(gè)特性,它們分別在ES2016, ES2017和ES2018中加入。
鑒于本文內(nèi)容很長(zhǎng),我們將分為兩個(gè)部分來(lái)介紹,此為第一部分。
1. Array.prototype.includes
includes是一個(gè)Array上很有用的函數(shù),用于快速查找數(shù)組中是否包含某個(gè)元素。(包括NaN,所以和indexOf不一樣)。
2. 指數(shù)函數(shù)的中綴形式
加/減法我們通常都是用其中綴形式,直觀易懂。在ECMAScript2016中,我們可以使用**來(lái)替代Math.pow。
1. Object.values()
Object.values()函數(shù)和Object.keys()很相似,它返回一個(gè)對(duì)象中自己屬性的所有值(通過(guò)原型鏈繼承的不算)。
2. Object.entries()
Object.entries()和Object.keys相關(guān),不過(guò)entries()函數(shù)會(huì)將key和value以數(shù)組的形式都返回。這樣,使用循環(huán)或則將對(duì)象轉(zhuǎn)為Map就很方便了。
例子1:
例子2:
3. 字符串追加
提供了兩個(gè)字符串追加的方法String.prototype.padStart和String.prototype.padEnd,方便我們將一個(gè)新的字符串追加到某個(gè)字符串的頭尾。
'someString'.padStart(numberOfCharcters [,stringForPadding]);
'5'.padStart(10) // ' 5'
'5'.padStart(10, '=*') //'=*=*=*=*=5'
'5'.padEnd(10) // '5 '
'5'.padEnd(10, '=*') //'5=*=*=*=*='
這個(gè)對(duì)于格式化輸出很有用!
3.1 padStart例子
我們有一個(gè)不同長(zhǎng)度元素的數(shù)組,我們可以往前面追加0來(lái)使得他們打印的長(zhǎng)度都為10。
3.2 padEnd例子
同樣,通過(guò)在后面追加字符串來(lái)格式化輸出。
const cars = {
'??BMW': '10',
'??Tesla': '5',
'??Lamborghini': '0'
}
Object.entries(cars).map(([name, count]) => {
//padEnd appends ' -' until the name becomes 20 characters
//padStart prepends '0' until the count becomes 3 characters.
console.log(`${name.padEnd(20, ' -')} Count: ${count.padStart(3, '0')}`)
});
//Prints..
// ??BMW - - - - - - - Count: 010
// ??Tesla - - - - - - Count: 005
// ??Lamborghini - - - Count: 000
3.3 使用padStart和padEnd來(lái)格式化Emojis和其他寬字符
Emojis和寬字符使用多個(gè)字節(jié)來(lái)表示,因此可能使用padStart和padEnd的結(jié)果并非如你所愿。
比如:我們追加??到heart前面:
//你會(huì)發(fā)現(xiàn)不僅沒有5個(gè)桃心,有一個(gè)桃心還很奇怪。
'heart'.padStart(10, "??"); // prints.. '?????heart'
這是因?yàn)??占有2個(gè)字節(jié)(‘\u2764\uFE0F’),而heart本身有5個(gè)字節(jié),因此只有5個(gè)字節(jié)的余地。所以只是追加了2個(gè)半的桃心。最后追加的’\u2764’會(huì)顯示為小黑桃心。
4. Object.getOwnPropertyDescriptors
該函數(shù)返回一個(gè)對(duì)象所有的屬性,甚至包括get/set函數(shù)。ES2017加入這個(gè)函數(shù)的主要?jiǎng)訖C(jī)在于方便將一個(gè)對(duì)象深度拷貝給另一個(gè)對(duì)象,同時(shí)可以將getter/setter拷貝。和Object.assign不同。
Object.assign將一個(gè)對(duì)象除了getter/setter以外的都深度拷貝了。
將原對(duì)象Car拷貝到ElectricCar,你就會(huì)發(fā)現(xiàn)Object.getOwnPropertyDescriptors拷貝了 getter和setter,而Object.assign沒有。
5. 允許在函數(shù)參數(shù)最后添加逗號(hào)
這是一個(gè)很小的改動(dòng),方便git算法更加方便區(qū)分代碼職責(zé)。我們用一個(gè)詳細(xì)的例子來(lái)理解:
值得一提的是,在函數(shù)調(diào)用的時(shí)候,也可以在最后添加逗號(hào)。
6. Async/Await
迄今為止,我介紹的特性中最有用的就屬這個(gè)功能了。Async函數(shù)可以幫助我們擺脫“回調(diào)地獄”,并且整個(gè)代碼會(huì)更加簡(jiǎn)潔。
async關(guān)鍵字告訴JavaScript編譯器對(duì)于標(biāo)定的函數(shù)要區(qū)別對(duì)待。當(dāng)編譯器遇到await函數(shù)的時(shí)候會(huì)暫停。它會(huì)等到await標(biāo)定的函數(shù)返回的promise。該promise要么得到結(jié)果、要么reject。
在下面的例子中,getAmount函數(shù)調(diào)用getUser和getBankBalance兩個(gè)異步函數(shù)。我們可以用promise來(lái)實(shí)現(xiàn)它,不過(guò)用async await更加簡(jiǎn)潔。
6.1 async函數(shù)返回Promise
如果你想獲取一個(gè)async函數(shù)的結(jié)果,你需要使用Promise的then語(yǔ)法。
在下面的例子中,我們想用console.log來(lái)打印doubleAndAdd的結(jié)果,可以使用then語(yǔ)法,將console.log函數(shù)作為參數(shù)傳入。
6.2 并行處理
在上面的例子中,我們顯示地調(diào)用了await兩次,因?yàn)槊看味嫉却?秒鐘,因此總計(jì)兩秒鐘?,F(xiàn)在,我們可以使用Promise.all函數(shù)來(lái)讓他們并行處理。
6.3 async/await的錯(cuò)誤處理
有很多方法來(lái)處理錯(cuò)誤。
- 方法1:在函數(shù)中使用try-catch
- 方法2:catch每一個(gè)await表達(dá)式
因?yàn)槊恳粋€(gè)await表達(dá)式都會(huì)返回Promise,你可以對(duì)一個(gè)進(jìn)行catch操作。
- 方法3:catch整個(gè)async-await函數(shù)


















