跳到主要内容

9 篇博文 含有标签「ES2019」

查看所有标签

将 JSON 嵌入 ECMAScript,也就是 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: 语法错误

// 一个包含原始 U+2029 字符的字符串,由 `eval` 生成:
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 爱好者

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}.`);
}
// 输出:
// The value of x is 42.
// The value of y is 50.

遗憾的是,想从 entries 的结果回到等价对象并不容易……直到现在!

Object.fromEntries

新的 Object.fromEntries API 执行了 Object.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 }

一个常见的用例是转换对象。现在可以通过迭代其条目,然后使用你已经熟悉的数组方法来做到这一点:

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 对剩余的条目进行操作,并为每个条目返回一个更新后的键值对。在本例中,我们通过将值乘以 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]]

格式良好的 `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'