當前位置:
首頁 > 知識 > 詳解 ES 2018 新特性

詳解 ES 2018 新特性

英文:Faraz Kelhini 譯文:展翅肥羊

https://www.zcfy.cc/article/new-es2018-features-every-javascript-developer-should-know

前言

以下將逐一解釋這些變動:

一、Rest/Spread 特性

ES2015中添加的最有趣的特性之一是spread操作符。你可以用它替換concat()和slice()方法,使數組的操作(複製、合併)更加簡單。

在數組必須以拆解的方式作為函數參數的情況下,spread操作符也很有用。例如:

ES2018通過向對象文本添加擴展屬性進一步擴展了這種語法。他可以將一個對象的屬性拷貝到另一個對象上,參考以下情形:

在上述代碼中,spread操作符遍歷obj1屬性,並將其添加到obj2的屬性中;而在之前的版本中,如此處理會拋出一個異常。需要注意的是,如果存在相同的屬性名,只有最後一個會生效。

同時,Spread操作符可以作為Object.assign() 的一個替代方案進行對象融合:

然而,在進行對象融合時,Spread操作結果並不總是與Object.assign()一致,例如:

在上述代碼中,Object.assign()方法繼承了setter屬性;而spread操作忽略了setter。

劃重點:spread只複製枚舉屬性。在下面的例子中,type屬性不會出現在複製對象中,因為它的枚舉屬性被設置為false:

繼承的屬性即使是可枚舉的也會被忽略:

在上述代碼中,car2繼承了car中的color屬性。因為spread操作只會複製對象自身的屬性,color並沒有出現在新的對象中。

spread只會進行淺拷貝,如果屬性的值是一個對象的話,只有對象的引用會被拷貝:

copy1.x 和 copy2.x 指向同一個對象的引用,所以他們嚴格相等。

ES2015增加的另一個有用特性是rest參數,它允許JS使用……將值表示為數組:

在上述代碼中,arr中的第一項分配給x,其餘元素分配給rest變數。這種模式稱為數組析構,非常流行,Ecma技術委員會決定為對象提供類似的功能:

這段代碼使用析構賦值中的rest屬性將剩餘的可枚舉屬性複製到一個新對象中。注意,rest屬性必須始終出現在對象的末尾,否則將拋出錯誤:

此外,在對象中使用多個rest語法會拋異常,除非它們是嵌套的:

Rest/Spread 特性支持

Node.js:

8.0.0 (需要 --harmony 運行環境)

8.3.0 (完全支持)

二、非同步迭代

遍歷是編程的一個重要部分。JS提供了for、for…in和while以及map()、filter()和forEach()等遍曆數據的方法。在ES2015則引入了迭代器介面。

包含Symbol.iterator屬性的對象是可迭代對象,如字元串和集合對象(如Set、Map和Array)。如下為迭代遍歷的示例:

Symbol.iterator是指定返回迭代器的函數. 迭代器包含next()方法,返回包含value和done屬性的對象。其中value為下一個元素,done為布爾值,表示遍歷是否結束。

普通對象進行迭代需要定義Symbol.iterator屬性。示例如下:

對象的迭代器通過Object.keys()方法獲取屬性名數組,將其賦值給values常量,同時定義一個默認值為0的計數器。當迭代器開始執行時,會返回一個包含next()方法的對象。該方法會返回包含value和done的對象,value為下一迭代值,done為布爾值,表示迭代器是否到達終點。

上述實現方式還是過於複雜,可以通過generator函數簡化:

在該generator函數中,利用for in循環枚舉生成屬性值。結果與前面的示例完全相同,但是要短得多。

迭代器的缺點是不適合表示非同步數據源。ES2018的解決方案是非同步迭代器和非同步迭代。非同步迭代器與傳統迭代器的不同之處在於,它沒有返回形式的普通對象,而是返回一個Promise,其resolve返回對象。一個可非同步迭代對象中包含Symbol.asyncIterator屬性(而不是Symbol.iterator),其功能為返回一個非同步迭代器。

如下示例應該會使這一點更清楚:

注意,promise 迭代器並不能代替非同步迭代器。雖然一個普通的同步迭代器可以非同步地確定值,但是它仍然需要同步地確定「完成」的狀態。

當然,您同樣可以使用generator函數簡化該過程,如下所示:

同樣,非同步迭代執行後會返回一個包含next()方法的對象。調用next()會返回一個包含的對象,而value值則變為一個promise對象

在可迭代對象上迭代的一個簡單方法是使用for of,但由於非同步迭代對象的value和done並不是同步指定的,因此for of並不適用。基於此,ES2018提供了for await of方法。讓我們來看一個例子:

在本代碼中,for await of語句隱式調用了Symbol.asyncIterator方法。在每次循環時,都會調用迭代器的next()方法,該方法返回一個promise。promise對象的value屬性將被讀入x變數。循環繼續,直到返回對象的done屬性的值為true。

注意:for await of語句僅在非同步生成器和非同步函數中有效。違反此規則會報SyntaxError錯誤。

next()方法可能返回一個包含rejects的promise。要優雅地處理,你可以把for await of用try catch包裹,如下所示:

非同步迭代器支持

Node.js:

8.10.0 (需要--harmony\ async\ iteration標誌)

10.0.0 (全部支持)

ES2018的另一個令人興奮的新特性是finally()方法。幾個JavaScript庫以前實現過類似的方法,這在許多情況下都很有用。這鼓勵Ecma技術委員會正式將finally()添加到規範中。無論promise的結果如何,finally()方法中的代碼都會執行。讓我們看一個簡單的例子:

無論操作是否成功,當您需要在操作完成後進行一些清理時,finally()方法就派上用場了。在這段代碼中,finally()方法在請求數據之後隱藏loading,無論請求是否成功。

您可以使用promise來實現相同的結果,使用then(func, func)而不是promise.finally(func),但是你必須在fulfillment handler和rejection handler中重複相同的代碼,或者為它聲明一個變數:

與then()和catch()一樣,finally()方法總是返回一個promise,因此可以鏈接更多的方法。通常,您希望使用finally()作為最後一個鏈,但是在某些情況下,例如在發出HTTP請求時,最好將另一個catch()鏈接起來,以處理finally()中可能出現的錯誤。

Node.js:10.0.0 (全部支持)

四、新的正則表達式特性

ES2018為正則表達式添加了四個新特性,進一步提高了JavaScript的字元串處理能力。這些特點如下:

s (dotAll) 標誌

命名捕獲組

Lookbehind 後行斷言

Unicode屬性轉義

s (dotAll) 標誌

點(.)是正則表達式模式中的一個特殊字元,它匹配除換行符(如換行符(\n)或回車符(\r)之外的任何字元。匹配所有字元(包括換行符)的一種方法是使用一個包含兩個短字元的字元類,比如[\d\D]。這個表達式查詢數字(\d)或非數字(\D)字元。因此,它匹配任何字元:

ES2018引入了一種模式,在這種模式中,點(.)可以用來實現相同的結果。通過在原正則表達式基礎上添加s表示,可以激活該模式:

使用標誌位來定義新行為的好處是向後兼容性。因此,使用點字元的現有正則表達式模式不受影響。

命名捕獲組

在一些正則表達式模式中,使用數字進行匹配可能會令人混淆。例如,使用正則表達式/(\d)-(\d)-(\d)/來匹配日期。因為美式英語中的日期表示法和英式英語中的日期表示法不同,所以很難區分哪一組表示日期,哪一組表示月份:

ES2018引入了使用(?…)語法的命名捕獲組。因此,匹配日期的模式可以用一種不那麼模稜兩可的方式來寫:

你可以在一個正則表達式中使用\k語法重複調用名稱捕獲組。例如,要在一個句子中找到連續重複的單詞,可以使用/\b(?\w )\s \k\b/:

要將命名捕獲組插入replace()方法的替換字元串中,需要使用$構造。例如:

Lookbehind後行斷言

ES2018將lookbehind後行斷言引入JavaScript,以前JavaScript只支持前行斷言。後行斷言由(?

還有一種負向後行斷言,表示為(?

Unicode 屬性轉義

ES2018提供了一種新的轉義序列類型,稱為Unicode屬性轉義,可以匹配所有的Unicode。你可以使用\p來匹配所有的Unicode數字,例如,假設你想匹配的Unicode字元?字元串:

同樣的,你可以使用\p來匹配所有的Unicode單詞字元:

同樣有一個負向的Unicode屬性轉義模板 \P{...}:

除了字母和數字之外,Unicode屬性轉義中還可以使用其他一些屬性。您可以在現行規範中找到受支持的Unicode屬性列表。

新正則表達式支持

Node.js:

8.3.0 (需要 --harmony 標誌)

8.10.0 (支持 s (dotAll) 標誌和後行斷言)

10.0.0 (全部支持)

五、 模板文字修訂

當模板文字前緊跟著一個表達式時,它被稱為帶標記的模板文字。當您想用函數解析模板文字時,帶標記的模板就派上用場了。考慮下面的例子:

在這段代碼中,模板文字調用了一個標記表達式(函數):修改字元串中的變數部分。

在ES2018之前,標記模板文字具有與轉義序列相關的語法限制。後跟特定字元序列的反斜杠被視為特殊字元:十六進位轉義的\x、unicode轉義的\u和八進位轉義的\u。因此,像「C:\xxx\uuu」或「\ubuntu」這樣的字元串被解釋器認為是無效的轉義序列,並且會拋出一個SyntaxError。

ES2018從標記模板中移除這些限制,並不是拋出錯誤,而是將無效的轉義序列表示為undefined:

注意,在常規模板文字中使用非法轉義序列仍然會導致錯誤:

模板文字修訂支持

Node.js:

8.3.0 (需要 --harmony 標誌)

8.10.0 (全部支持)

總結

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 JavaScript 的精彩文章:

Vue 最黑暗的一天
重構項目,你真的準備好了嗎

TAG:JavaScript |