跳至主要内容

9 篇文章 含有標籤「ES2019」

檢視所有標籤

包括 JSON,即 JSON ⊂ ECMAScript

· 閱讀時間約 6 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

隨著提案 JSON ⊂ ECMAScript,JSON 成為 ECMAScript 的語法子集。如果你對此感到驚訝,並非只有你一個!

舊的 ES2018 行為

在 ES2018 中,ECMAScript 的字串文本不能包含未轉義的 U+2028 行分隔符和 U+2029 段落分隔符字元,因為即使在該上下文中,它們仍被認為是行終結符:

// 包含原始 U+2028 字元的字串。
const LS = '
';
// → ES2018: 語法錯誤

// 一個由 `eval` 生成的,包含原始 U+2029 字元的字串:
const PS = eval('"\u2029"');
// → ES2018: 語法錯誤

這是有問題的,因為 JSON 字串_可以_包含這些字元。因此,開發者在嵌入有效的 JSON 到 ECMAScript 程式中時,必須實現特殊的後處理邏輯來處理這些字元。沒有這樣的邏輯,程式碼可能會有細微的錯誤,甚至導致安全問題

穩定的 `Array.prototype.sort`

· 閱讀時間約 3 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

假設你有一個狗狗的陣列,每隻狗有一個名字和一個評級。(如果這聽起來是個奇怪的例子,你應該知道,Twitter 上有一個專門做這件事的賬號……請不要深究!)

// 注意,陣列已按 `name` 字母序排序。
const doggos = [
{ name: 'Abby', rating: 12 },
{ name: 'Bandit', rating: 13 },
{ name: 'Choco', rating: 14 },
{ name: 'Daisy', rating: 12 },
{ name: 'Elmo', rating: 12 },
{ name: 'Falco', rating: 13 },
{ name: 'Ghost', rating: 14 },
];
// 按 `rating` 降序排序狗狗。
// (會就地更新 `doggos`。)
doggos.sort((a, b) => b.rating - a.rating);

`Symbol.prototype.description`

· 閱讀時間約 1 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

JavaScript Symbol 在建立時可以給予一個描述:

const symbol = Symbol('foo');
// ^^^^^

以前,要以程式方式存取這個描述的唯一方法是透過 Symbol.prototype.toString() 間接取得:

const symbol = Symbol('foo');
// ^^^^^
symbol.toString();
// → 'Symbol(foo)'
// ^^^
symbol.toString().slice(7, -1); // 🤔
// → 'foo'

然而,這段程式碼看起來有點神秘,不太容易理解,並且違反了“表達意圖,而不是實作”的原則。上述技術也無法區分沒有描述的 Symbol (即 Symbol())和描述為空字串的 Symbol(即 Symbol(''))。

`Object.fromEntries`

· 閱讀時間約 4 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias)), JavaScript whisperer

Object.fromEntries 是 JavaScript 內建函式庫的一個實用新增功能。在解釋它的功能之前,了解現有的 Object.entries API 會有所幫助。

Object.entries

Object.entries API 已經存在一段時間了。

對於物件中的每個鍵值對,Object.entries 會返回一個陣列,第一個元素是鍵,第二個元素是值。

Object.entries 尤其在與 for-of 結合使用時非常有用,因為它能讓你非常優雅地遍歷物件中的所有鍵值對:

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

for (const [key, value] of entries) {
console.log(`The value of ${key} is ${value}.`);
}
// 日誌:
// x 的值是 42。
// y 的值是 50。

不幸的是,直到現在,還沒有一個簡單的方法可以將 entries 結果轉回到等效的物件。

Object.fromEntries

新的 Object.fromEntries API 執行了 Object.entries 的相反操作。這使得根據其 entries 重建物件變得簡單:

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

const result = Object.fromEntries(entries);
// → { x: 42, y: 50 }

一個常見的用例是轉換物件。現在你可以通過遍歷它的 entries,然後使用你可能已經熟悉的陣列方法來完成:

const object = { x: 42, y: 50, abc: 9001 };
const result = Object.fromEntries(
Object.entries(object)
.filter(([ key, value ]) => key.length === 1)
.map(([ key, value ]) => [ key, value * 2 ])
);
// → { x: 84, y: 100 }

在這個例子中,我們使用 filter 過濾物件來僅保留鍵長度為 1 的鍵,也就是僅保留鍵 xy,不包括鍵 abc。接著,我們用 map 遍歷剩下的 entries,並為每個返回更新的鍵值對。此例中,我們通過將值乘以 2 來使每個值加倍。最終結果是一個新物件,僅包含屬性 xy 及其新值。

`Array.prototype.flat` 和 `Array.prototype.flatMap`

· 閱讀時間約 2 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Array.prototype.flat

此範例中的陣列是多層嵌套的:它包含一個陣列,而這個陣列又包含另一個陣列。

const array = [1, [2, [3]]];
// ^^^^^^^^^^^^^ 外層陣列
// ^^^^^^^^ 內層陣列
// ^^^ 最內層陣列

Array#flat 回傳一個展平後的陣列。

array.flat();
// → [1, 2, [3]]

// …等同於:
array.flat(1);
// → [1, 2, [3]]

預設的展平深度是 1,但您可以傳入任何數字值來遞迴展平到該深度。若要持續展平直到結果不再包含嵌套陣列,可以使用 Infinity

// 持續遞迴展平直到陣列不再包含嵌套陣列:
array.flat(Infinity);
// → [1, 2, 3]

這個方法為什麼叫做 Array.prototype.flat 而不是 Array.prototype.flatten 呢?閱讀我們的 #SmooshGate 撰寫內容來了解!

Array.prototype.flatMap

以下是另一個範例。我們有一個 duplicate 函數,它接受一個值並回傳一個包含該值兩次的陣列。如果我們將 duplicate 套用到陣列中的每個值,我們會得到一個嵌套陣列。

const duplicate = (x) => [x, x];

[2, 3, 4].map(duplicate);
// → [[2, 2], [3, 3], [4, 4]]

接著您可以對結果呼叫 flat 來展平陣列:

[2, 3, 4].map(duplicate).flat(); // 🐌
// → [2, 2, 3, 3, 4, 4]

由於此模式在函數式編程中相當常見,因此現在有一個專屬的 flatMap 方法。

[2, 3, 4].flatMap(duplicate); // 🚀
// → [2, 2, 3, 3, 4, 4]

flatMap 比起分別執行 mapflat 更加高效。

flatMap 的使用案例感興趣嗎?請查看 Axel Rauschmayer 的解釋

Array#{flat,flatMap} 支援

格式良好的 `JSON.stringify`

· 閱讀時間約 1 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

JSON.stringify 之前的規範是當輸入包含任何孤立代理項時,返回格式不良的 Unicode 字串:

JSON.stringify('\uD800');
// → '"�"'

“格式良好的 JSON.stringify”提案 修改了 JSON.stringify,使其對孤立代理項輸出轉義序列,令其輸出有效 Unicode(並且可在 UTF-8 中表示):

可選擇 `catch` 綁定

· 閱讀時間約 1 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

try 語句的 catch 子句以往需要一個綁定:

try {
doSomethingThatMightThrow();
} catch (exception) {
// ^^^^^^^^^
// 我們必須命名這個綁定,縱使我們不使用它!
handleException();
}

在 ES2019,catch 現在可以在沒有綁定的情況下使用。如果您在處理異常的代碼中不需要 exception 對象時,這很實用。

try {
doSomethingThatMightThrow();
} catch { // → 無綁定!
handleException();
}

可選擇的 catch 綁定支持

`String.prototype.trimStart` 和 `String.prototype.trimEnd`

· 閱讀時間約 1 分鐘
Mathias Bynens ([@mathias](https://twitter.com/mathias))

ES2019 引入了 String.prototype.trimStart()String.prototype.trimEnd():

const string = '  hello world  ';
string.trimStart();
// → 'hello world '
string.trimEnd();
// → ' hello world'
string.trim(); // ES5
// → 'hello world'

此功能之前可以通過非標準的 trimLeft()trimRight() 方法實現,這些方法仍然作為新方法的別名保留,從而保證向後兼容性。

const string = '  hello world  ';
string.trimStart();
// → 'hello world '
string.trimLeft();
// → 'hello world '
string.trimEnd();
// → ' hello world'
string.trimRight();
// → ' hello world'
string.trim(); // ES5
// → 'hello world'