[譯]ES2018(ES9)的新特性
原文連結:www.sitepoint.com/es2018-what…
在這篇文章中,我將介紹ES2018(ES9)的新特性,並介紹如何使用它們。
JavaScript(ECMAScript)是跨多個平臺的許多廠商實施的不斷髮展的標準。ES6(ECMAScript 2015)花費六年的時間敲定,是一個很大的發行版。新的年度釋出流程被制定,以簡化流程並更快地新增功能。 ES9(ES2018)是撰寫本文時的最新版本。
TC39由包括瀏覽器廠商在內的各方組成,他們開會推動JavaScript提案沿著一條嚴格的發展道路前進:
- Stage 0: strawman——最初想法的提交。
- Stage 1: proposal(提案)——由TC39至少一名成員倡導的正式提案檔案,該檔案包括API事例。
- Stage 2: draft(草案)——功能規範的初始版本,該版本包含功能規範的兩個實驗實現。
- Stage 3: candidate(候選)——提案規範通過審查並從廠商那裡收集反饋
- Stage 4: finished(完成)——提案准備加入ECMAScript,但是到瀏覽器或者Nodejs中可能需要更長的時間
ES2016
ES2016新增了兩個小的特性來說明標準化過程:
- 陣列
includes()
方法,用來判斷一個陣列是否包含一個指定的值,根據情況,如果包含則返回true
,否則返回false
。 -
a ** b
指數運算子,它與Math.pow(a, b)
相同。
ES2017
ES2017提供了更多的新特性:
- Async 函式呈現更清晰的 Promise 語法
-
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
ES2018
ECMAScript 2018(或者叫ES9)現在已經可用了。以下功能已經到達 stage 4,但是在撰寫本文時在各個瀏覽器的實現還不完整。
非同步迭代
在async/await
的某些時刻,你可能嘗試在同步迴圈中呼叫非同步函式。例如:
async function process(array) {
for (let i of array) {
await doSomething(i);
}
}
這段程式碼不會正常執行,下面這段同樣也不會:
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.finally()
一個Promise呼叫鏈要麼成功到達最後一個.then()
,要麼失敗觸發.catch()
。在某些情況下,你想要在無論Promise執行成功還是失敗,執行相同的程式碼,例如清除,刪除對話,關閉資料庫連線等。
.finally()
允許你指定最終的邏輯:
function doSomething() {
doSomething1()
.then(doSomething2)
.then(doSomething3)
.catch(err => {
console.log(err);
})
.finally(() => {
// finish here!
});
}
Rest/Spread 屬性
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。
正規表示式命名捕獲組(Regular Expression Named Capture Groups)
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>`);
正規表示式反向斷言(lookbehind)
目前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
world`); // false
/hello.world/s.test(`hello
world`); // true
正規表示式 Unicode 轉義
到目前為止,在正規表示式中本地訪問 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:uuuxxx111
。更多細節參考模板字串。
這是所有的ES2018的新特性,ES2019已經開始,你有什麼期待的功能想在明年看到嗎?
譯者參考
相關文章
- [譯] ES2018(ES9)的新特性
- 【譯】ES2018 新特性:Rest/Spread 特性REST
- 【譯】ES2018 新特性:Promise.prototype.finally()Promise
- 【譯】ES2018 新特性: 正規表示式的 s (dotAll) 標誌
- ECMAScript 2018(ES9)新特性簡介
- ES9的新特性:正規表示式RegExp
- ES9的新特性:非同步遍歷Async iteration非同步
- ES2018 新增特性清單
- 〔譯〕TypeScript 2.0 的新特性TypeScript
- 細解JavaScript ES7 ES8 ES9 新特性JavaScript
- 每個 JavaScript 開發者都該瞭解的 ES2018 新特性JavaScript
- [譯] Swift 5.0 新特性Swift
- [譯] Chrome 71 新特性介紹Chrome
- [譯]React v16.9 新特性React
- 每個JavaScript開發人員都應該知道的新ES2018功能(譯文)JavaScript
- ES6、ES7、ES8、ES9、ES10新特性一覽
- 如何給 PHP 新增新的語法特性 (譯)PHP
- 原創翻譯-Java 8新特性Java
- 最全的Vue3.0新特性預覽(翻譯)Vue
- 【譯】.NET 5. 0 中 Windows Form 的新特性WindowsORM
- [譯] Chrome 73 開發者工具新特性Chrome
- [譯] 新的 CSS 特性正在改變網頁設計CSS網頁
- ES2018 新特徵之:非轉義序列的模板字串特徵字串
- ES2018 新特徵之:正規表示式 dotAll 模式特徵模式
- 新特性
- Swift 4.1 的新特性Swift
- ES的那些新特性
- 玩轉iOS開發:iOS 11 新特性《Layout的新特性》iOS
- [譯] Swift 中的動態特性Swift
- [譯] PowerShell Core 6.0 的新增特性
- C# 9 新特性:程式碼生成器、編譯時反射C#編譯反射
- Java12的新特性Java
- Go 1.12 版本的新特性Go
- mysql5.1的新特性MySql
- Java 11 的新特性(下)Java
- Java21的新特性Java
- PHP7.0 的新特性PHP
- php7的新特性PHP