ES10 雖然沒有像 ES6 那麼多新特性,但 ES10 仍然有一些有用的特性。文本通過簡單示例來介紹了 ES10 新出來的特性。通過這種方式,咱們就可以快速理解,而不需要看太多的官方解釋。
ES10 新特性主要如下:
- 數組方法:flat和flatMap
- Object.fromEntries
- 字符串方法:trimStart 和 trimEnd
- Symbol 的 description 屬性
- try { } catch {} // catch 的參數可以省略了
- JSON ⊂ ECMAScript (讓 ECMAScript 兼容所有 JSON 支持的文本)
- 格式良好的 JSON.stringify()
- 穩定的 Array.prototype.sort()
- 修正後的 Function.toString
- BigInt 是第七種 原始類型
- 動態導入
- 標準化 globalThis 對象
1. Array.flat() && Array.flatMap
Array.flat() 方法會按照一個可指定的深度遞歸遍歷數組,並將所有元素與遍歷到的子數組中的元素合併為一個新數組返回。
Array.flatMap() 方法首先使用映射函數映射每個元素,然後將結果壓縮成一個新數組。它與 map 和 深度值1的 flat 幾乎相同,但 flatMap 通常在合併成一種方法的效率稍微高一些。
Array.flat()
Array.flatMap()
綜合示例:
2.Object.fromEntries()
Object.fromEntries() 方法把鍵值對列表轉換為一個對象。
事例一:
事例二:
3.String.protype.matchAll
早期的一個問題是,如何編寫正則表達式“match all”?
最佳的答案將建議 String.match 與正則表達式和 /g 一起使用或者帶有 /g 的 RegExp.exec 或者帶有 /g 的 RegExp.test 。
咱們先看看舊規範是如何工作的。
帶字符串參數的 String.match 僅返回第一個匹配:
結果是單個 "l"(注意:匹配存儲在 matches[0] 中而不是 matches)
將 string.match 與 regex 參數一起使用也是如此:
使用正則表達式 /l/ 找到字符 串“hello” 中的 “l” 字符:
添加 /g 混合
那麼為什麼要使用全新的 matchAll 方法呢? 在解疑這個問題之前,先來看看 捕獲組。
正則表達式捕獲組
在 regex 中捕獲組只是從 () 括號中提取一個模式,可以使用 /regex/.exec(string) 和string.match 捕捉組。
常規捕獲組是通過將模式包裝在 (pattern) 中創建的,但是要在結果對象上創建 groups 屬性,它是: (?<name>pattern)。/<name>
要創建一個新的組名,只需在括號內附加 ?<name>,結果中,分組 (pattern) 匹配將成為 group.name,並附加到 match 對象,以下是一個實例:/<name>
字符串標本匹配:
這裡創建了 match.groups.color 和 match.groups.bird :
需要多次調用 regex.exec 方法來遍歷整個搜索結果集。 在每次迭代期間調用.exec 時,將顯示下一個結果(它不會立即返回所有匹配項),因此使用 while 循環。
輸出如下:
但奇怪的是:
如果你從這個正則表達式中刪除 /g,你將永遠在第一個結果上創建一個無限循環。這在過去是一個巨大的痛苦。想象一下,從某個數據庫接收正則表達式時,你不確定它的末尾是否有 /g,你得先檢查一下。
使用 .matchAll() 的好理由
.matchAll() 是如何工作的?
咱們嘗試匹配單詞 hello 中字母 e 和 l 的所有實例, 因為返回了迭代器,所以可以使用 for…of 循環遍歷它:
這一次你可以跳過 /g, .matchall 方法不需要它,結果如下:
使用 .matchAll() 捕獲組示例:
請注意已經沒有 /g 標誌,因為 .matchAll() 已經包含了它,打印如下:
也許在美學上它與原始正則表達式非常相似,執行while循環實現。但是如前所述,由於上面提到的許多原因,這是更好的方法,移除 /g 不會導致無限循環。
綜合事例:
4.String.trimStart() 與 String.trimEnd()
trimStart() :刪除字符串的開頭空格。
trimEnd() :刪除字符串末尾的空格。
事例一:
事例二:
5.Symbol.Description
description 是一個只讀屬性,它會返回 Symbol 對象的可選描述的字符串。
事例一:
事例二:
6.catch 的參數可以省略
在過去,try/catch 語句中的 catch 語句需要一個變量。 try/catch 語句幫助捕獲終端級別的錯誤:
在某些情況下,所需的錯誤變量是未使用的:
在 ES10 中,捕獲錯誤的變量是可選的,現在可以跳過錯誤變量:
事例一:
事例二:
7. JSON ⊂ ECMAScript
什麼是 JSON 超集?還記得 ⊂ 這個符號的可以這樣解釋該提案 JSON ⊂ ECMAScript,簡而言之就是讓 ECMAScript 兼容所有 JSON 支持的文本。ECMAScript 曾在標準 JSON.parse 部分闡明 JSON 確為其一個子集,但由於 JSON 內容可以正常包含 U+2028 行分隔符與 U+2029 段落分隔符而 ECMAScript 卻不行。
該草案旨在解決這一問題。在這之前,如果你使用 JSON.parse() 執行帶如上特殊字符的字符串時,只會收到 SyntaxError 的錯誤提示。該草案同樣是向後兼容的,其對用戶唯一的影響是保持原樣,即在暫不支持特殊字符解析的運行環境中保持 SyntaxError 的報錯。
8.格式良好的 JSON.stringify()
此更新修復了字符 U+D800 到 U+DFFF 的處理,有時可以進入 JSON 字符串。 這可能是一個問題,因為 JSON.stringify 可能會將這些數字格式化為沒有等效 UTF-8 字符的值, 但 JSON 格式需要 UTF-8 編碼。
解析方法使用格式良好的JSON字符串,如:
<code>'{ “prop1” : 1, "prop2" : 2 }'; // A well-formed JSON format string/<code>
注意,要創建正確 JSON 格式的字符串,絕對需要在屬性名周圍加上雙引號。缺少或任何其他類型的引號都不會生成格式良好的JSON。
<code>'{ “prop1” : 1, "meth" : () => {}}'; // Not JSON format string/<code>
JSON 字符串格式與 Object Literal 不同,後者看起來幾乎一樣,但可以使用任何類型的引號括住屬性名,也可以包含方法(JSON格式不允許使用方法):
<code>let object_literal = { property: 1, meth: () => {} };/<code>
不管怎樣,一切似乎都很好。第一個示例看起來是兼容的。但它們也是簡單的例子,大多數情況下都能順利地工作!
U+2028 和 U+2029 字符
問題是, ES10 之前的 EcmaScript 實際上並不完全支持 JSON 格式。前 ES10 時代不接受未轉義行分隔符 U+2028 和段落分隔符 U+2029 字符:
對於 U+D800 - U+DFFF 之間的所有字符也是如此
如果這些字符潛入 JSON 格式的字符串(假設來自數據庫記錄),你可能會花費數小時試圖弄清楚為什麼程序的其餘部分會產生解析錯誤。
因此,如果你傳遞 eval 這樣的字符串 “console.log(' hello ')”,它將執行 JS語句 (通過嘗試將字符串轉換為實際代碼),也類似於 JSON.parse 將處理你的 JSON 字符串的方式。
ES10建議的解決方案是將未配對的代理代碼點表示為JSON轉義序列,而不是將它們作為單個UTF-16代碼單元返回。
9.穩定的 Array.prototype.sort()
V8 之前的實現對包含10個以上項的數組使用了一種不穩定的快速排序算法。
一個穩定的排序算法是當兩個鍵值相等的對象在排序後的輸出中出現的順序與在未排序的輸入中出現的順序相同時。
但情況不再是這樣了,ES10 提供了一個穩定的數組排序:
控制檯輸出(項目以相反的順序出現):
事例二:
10.新的 Function.toString()
函數是對象,並且每個對象都有一個 .toString() 方法,因為它最初存在於Object.prototype.toString() 上。 所有對象(包括函數)都是通過基於原型的類繼承從它繼承的。
這意味著我們以前已經有 funcion.toString() 方法了。
但是 ES10 進一步嘗試標準化所有對象和內置函數的字符串表示。 以下是各種新案例:
典型的例子:
<code>function () { console.log('Hello there.'); }.toString();/<code>
輸出:
<code>⇨ function () { console.log('Hello there.'); }/<code>
直接在方法名 .toString()
<code>Number.parseInt.toString();
⇨ function parseInt() { [native code] }/<code>
綁定上下文:
<code>function () { }.bind(0).toString();
⇨ function () { [native code] }/<code>
內置可調用函數對象:
<code>Symbol.toString();
⇨ function Symbol() { [native code] }/<code>
動態生成的函數:
<code>function* () { }.toString();
⇨ function* () { }/<code>
prototype.toString
<code>Function.prototype.toString.call({});
⇨ Function.prototype.toString requires that 'this' be a Function"/<code>
11.BigInt -任意精度整數
BigInt 是第七種 原始類型。
BigInt 是一個任意精度的整數。這意味著變量現在可以 表示²⁵³ 數字,而不僅僅是9007199254740992。
<code>const b = 1n; // 追加 n 以創建 BigInt/<code>
在過去,不支持大於 9007199254740992 的整數值。如果超過,該值將鎖定為 MAX_SAFE_INTEGER + 1:
12.動態導入
動態導入返回請求模塊的模塊名稱空間對象的promise 。因此,可以配合使用async/await。
事例一:
事例二:
13.標準化 globalThis 對象
這在ES10之前, globalThis 還沒有標準化,在平時的項目可以通過以下方式來兼容不同的平臺:
但即使這樣也不總是奏效。因此,ES10 添加了 globalThis 對象,從現在開始,該對象用於在任何平臺上訪問全局作用域:
但即使這樣也不總是奏效。因此,ES10 添加了 globalThis 對象,從現在開始,該對象用於在任何平臺上訪問全局作用域:
總結
JS 是一種動態語言,這對 web 開發非常有益。自 2015 年 ES6 出現以來,JS 語言經歷了一次充滿活力的演變。在這篇文章中,咱們回顧了ES10(2019)中出現的特性,並介紹了一些將在ES11(2020)中保持穩定的特性,因為它們處於
state 3,並且很可能在下一個版本中被標準化。儘管這些特性中的許多對於Web應用程序的開發可能不是必需的,但是一些特性可以規制咱們以前通過技巧或大量冗長實現的代碼。
原文:https://dev.to/carlillo/12-es10-features-in-12-simple-examples-2cbn
閱讀更多 前端小智 的文章
關鍵字: 字長 重溫 ECMAScript