[譯] ES2018(ES9)的新特性

原文連接:www.sitepoint.com/es2018-what…javascript

在這篇文章中,我將介紹ES2018(ES9)的新特性,並介紹如何使用它們。html

JavaScript(ECMAScript)是跨多個平臺的許多廠商實施的不斷髮展的標準。ES6(ECMAScript 2015)花費六年的時間敲定,是一個很大的發行版。新的年度發佈流程被制定,以簡化流程並更快地添加功能。 ES9(ES2018)是撰寫本文時的最新版本。java

TC39由包括瀏覽器廠商在內的各方組成,他們開會推進JavaScript提案沿着一條嚴格的發展道路前進:正則表達式

  • Stage 0: strawman——最初想法的提交。
  • Stage 1: proposal(提案)——由TC39至少一名成員倡導的正式提案文件,該文件包括API事例。
  • Stage 2: draft(草案)——功能規範的初始版本,該版本包含功能規範的兩個實驗實現。
  • Stage 3: candidate(候選)——提案規範經過審查並從廠商那裏收集反饋
  • Stage 4: finished(完成)——提案准備加入ECMAScript,可是到瀏覽器或者Nodejs中可能須要更長的時間

ES2016

ES2016添加了兩個小的特性來講明標準化過程:數據庫

  1. 數組includes()方法,用來判斷一個數組是否包含一個指定的值,根據狀況,若是包含則返回true,不然返回false
  2. a ** b指數運算符,它與 Math.pow(a, b)相同。

ES2017

ES2017提供了更多的新特性:segmentfault

  1. Async 函數呈現更清晰的 Promise 語法
  2. Object.values 方法返回一個給定對象本身的全部可枚舉屬性值的數組,值的順序與使用for...in循環的順序相同(區別在於for...in循環枚舉原型鏈中的屬性)
  3. Object.entries()方法返回一個給定對象自身可枚舉屬性的鍵值對數組,其排列與使用for...in循環遍歷改對象時返回的順序一致(區別在於for...in循環也枚舉原型鏈中的屬性)
  4. Object.getOwnPropertyDescriptors()返回一個對象的全部自身屬性的描述符(.value,.writable,.get,.set,.configurable,enumerable
  5. padStart()padEnd(),填充字符串達到當前長度
  6. 結尾逗號,數組定義和函數參數列表
  7. ShareArrayBufferAtomics用於從共享內存位置讀取和寫入

關於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

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\nworld');  // false
/hello.world/s.test('hello\nworld'); // 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:\uuu\xxx\111。更多細節參考模板字符串

這是全部的ES2018的新特性,ES2019已經開始,你有什麼期待的功能想在明年看到嗎?

譯者參考

相關文章
相關標籤/搜索