原文連接:www.sitepoint.com/es2018-what…javascript
在這篇文章中,我將介紹ES2018(ES9)的新特性,並介紹如何使用它們。html
JavaScript(ECMAScript)是跨多個平臺的許多廠商實施的不斷髮展的標準。ES6(ECMAScript 2015)花費六年的時間敲定,是一個很大的發行版。新的年度發佈流程被制定,以簡化流程並更快地添加功能。 ES9(ES2018)是撰寫本文時的最新版本。java
TC39由包括瀏覽器廠商在內的各方組成,他們開會推進JavaScript提案沿着一條嚴格的發展道路前進:正則表達式
ES2016添加了兩個小的特性來講明標準化過程:數據庫
includes()
方法,用來判斷一個數組是否包含一個指定的值,根據狀況,若是包含則返回true
,不然返回false
。a ** b
指數運算符,它與 Math.pow(a, b)
相同。ES2017提供了更多的新特性:segmentfault
Object.values
方法返回一個給定對象本身的全部可枚舉屬性值的數組,值的順序與使用for...in
循環的順序相同(區別在於for...in
循環枚舉原型鏈中的屬性)Object.entries()
方法返回一個給定對象自身可枚舉屬性的鍵值對數組,其排列與使用for...in
循環遍歷改對象時返回的順序一致(區別在於for...in
循環也枚舉原型鏈中的屬性)Object.getOwnPropertyDescriptors()
返回一個對象的全部自身屬性的描述符(.value
,.writable
,.get
,.set
,.configurable
,enumerable
)padStart()
和padEnd()
,填充字符串達到當前長度ShareArrayBuffer
和Atomics
用於從共享內存位置讀取和寫入關於ES2017的更多信息請參閱 What's New in ES2017數組
ECMAScript 2018(或者叫ES9)如今已經可用了。如下功能已經到達 stage 4,可是在撰寫本文時在各個瀏覽器的實現還不完整。瀏覽器
在async/await
的某些時刻,你可能嘗試在同步循環中調用異步函數。例如:異步
async function process(array) {
for (let i of array) {
await doSomething(i);
}
}
複製代碼
這段代碼不會正常運行,下面這段一樣也不會:async
async function process(array) {
array.forEach(async i => {
await doSomething(i);
});
}
複製代碼
這段代碼中,循環自己依舊保持同步,並在在內部異步函數以前所有調用完成。
ES2018引入異步迭代器(asynchronous iterators),這就像常規迭代器,除了next()
方法返回一個Promise。所以await
能夠和for...of
循環一塊兒使用,以串行的方式運行異步操做。例如:
async function process(array) {
for await (let i of array) {
doSomething(i);
}
}
複製代碼
一個Promise調用鏈要麼成功到達最後一個.then()
,要麼失敗觸發.catch()
。在某些狀況下,你想要在不管Promise運行成功仍是失敗,運行相同的代碼,例如清除,刪除對話,關閉數據庫鏈接等。
.finally()
容許你指定最終的邏輯:
function doSomething() {
doSomething1()
.then(doSomething2)
.then(doSomething3)
.catch(err => {
console.log(err);
})
.finally(() => {
// finish here!
});
}
複製代碼
ES2015引入了Rest參數和擴展運算符。三個點(...)僅用於數組。Rest參數語法容許咱們將一個布丁數量的參數表示爲一個數組。
restParam(1, 2, 3, 4, 5);
function restParam(p1, p2, ...p3) {
// p1 = 1
// p2 = 2
// p3 = [3, 4, 5]
}
複製代碼
展開操做符以相反的方式工做,將數組轉換成可傳遞給函數的單獨參數。例如Math.max()
返回給定數字中的最大值:
const values = [99, 100, -1, 48, 16];
console.log( Math.max(...values) ); // 100
複製代碼
ES2018爲對象解構提供了和數組同樣的Rest參數()和展開操做符,一個簡單的例子:
const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...x } = myObject;
// a = 1
// x = { b: 2, c: 3 }
複製代碼
或者你可使用它給函數傳遞參數:
restParam({
a: 1,
b: 2,
c: 3
});
function restParam({ a, ...x }) {
// a = 1
// x = { b: 2, c: 3 }
}
複製代碼
跟數組同樣,Rest參數只能在聲明的結尾處使用。此外,它只適用於每一個對象的頂層,若是對象中嵌套對象則沒法適用。
擴展運算符能夠在其餘對象內使用,例如:
const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { ...obj1, z: 26 };
// obj2 is { a: 1, b: 2, c: 3, z: 26 }
複製代碼
可使用擴展運算符拷貝一個對象,像是這樣obj2 = {...obj1}
,可是 這只是一個對象的淺拷貝。另外,若是一個對象A的屬性是對象B,那麼在克隆後的對象cloneB中,該屬性指向對象B。
JavaScript正則表達式能夠返回一個匹配的對象——一個包含匹配字符串的類數組,例如:以YYYY-MM-DD的格式解析日期:
const
reDate = /([0-9]{4})-([0-9]{2})-([0-9]{2})/,
match = reDate.exec('2018-04-30'),
year = match[1], // 2018
month = match[2], // 04
day = match[3]; // 30
複製代碼
這樣的代碼很難讀懂,而且改變正則表達式的結構有可能改變匹配對象的索引。
ES2018容許命名捕獲組使用符號?<name>
,在打開捕獲括號(
後當即命名,示例以下:
const
reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/,
match = reDate.exec('2018-04-30'),
year = match.groups.year, // 2018
month = match.groups.month, // 04
day = match.groups.day; // 30
複製代碼
任何匹配失敗的命名組都將返回undefined
。
命名捕獲也可使用在replace()
方法中。例如將日期轉換爲美國的 MM-DD-YYYY 格式:
const
reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/,
d = '2018-04-30',
usDate = d.replace(reDate, '$<month>-$<day>-$<year>');
複製代碼
目前JavaScript在正則表達式中支持先行斷言(lookahead)。這意味着匹配會發生,但不會有任何捕獲,而且斷言沒有包含在整個匹配字段中。例如從價格中捕獲貨幣符號:
const
reLookahead = /\D(?=\d+)/,
match = reLookahead.exec('$123.89');
console.log( match[0] ); // $
複製代碼
ES2018引入以相同方式工做可是匹配前面的反向斷言(lookbehind),這樣我就能夠忽略貨幣符號,單純的捕獲價格的數字:
const
reLookbehind = /(?<=\D)\d+/,
match = reLookbehind.exec('$123.89');
console.log( match[0] ); // 123.89
複製代碼
以上是 確定反向斷言,非數字\D
必須存在。一樣的,還存在 否認反向斷言,表示一個值必須不存在,例如:
const
reLookbehindNeg = /(?<!\D)\d+/,
match = reLookbehind.exec('$123.89');
console.log( match[0] ); // null
複製代碼
dotAll
模式正則表達式中點.
匹配除回車外的任何單字符,標記s
改變這種行爲,容許行終止符的出現,例如:
/hello.world/.test('hello\nworld'); // false
/hello.world/s.test('hello\nworld'); // true
複製代碼
到目前爲止,在正則表達式中本地訪問 Unicode 字符屬性是不被容許的。ES2018添加了 Unicode 屬性轉義——形式爲\p{...}
和\P{...}
,在正則表達式中使用標記 u
(unicode) 設置,在\p
塊兒內,能夠以鍵值對的方式設置須要匹配的屬性而非具體內容。例如:
const reGreekSymbol = /\p{Script=Greek}/u;
reGreekSymbol.test('π'); // true
複製代碼
此特性能夠避免使用特定 Unicode 區間來進行內容類型判斷,提高可讀性和可維護性。
最後,ES2018 移除對 ECMAScript 在帶標籤的模版字符串中轉義序列的語法限制。
以前,\u
開始一個 unicode 轉義,\x
開始一個十六進制轉義,\
後跟一個數字開始一個八進制轉義。這使得建立特定的字符串變得不可能,例如Windows文件路徑 C:\uuu\xxx\111
。更多細節參考模板字符串。
這是全部的ES2018的新特性,ES2019已經開始,你有什麼期待的功能想在明年看到嗎?