ES2020 特性集尘埃落定

发布于:2020 年 4 月 14 日 12:34

ES2020特性集尘埃落定

TC39 委员会于近期批准了 ECMAScript 2020(即 ES2020)候选提案,即经审定最终添加到 JavaScript 语言中的特性集。ES2020 候选提案是今年六月提交 ECMA 大会(General Assembly)的审批汇总,其中的大部分新特性已在浏览器中得到实现,并已可被 Babel JavaScript 解析器转码(transpile)。

在 ES2020 规范中,为 String 对象引入了新的 matchAll 方法,该方法根据一个全局正则表达式生成所有匹配对象的一个迭代器;在语法上支持 import(),使用动态描述符异步导入模块;支持任意精度整型的 BigInt 类型;Promise 新的组合器 Promise.allSettled,它不会造成短路;提供访问全局 this 值的通用操作方式 globalThis;模块内使用的 export * as ns from 'module’专用语法;进一步规范化的 for-in 枚举属性顺序;模块中可包含依赖于宿主环境上下文相关信息的 import.meta 特性;以及改进对空位(即 null 和 undefined)处理的两个新语法特性,即值选取操作符“空位合并”(nullish coalescing),和“可选链”(optional chaining),一种一旦所访问或调用的值为空位时采取短路的访问 / 调用操作符。

动态导入( Dynamic imports )特性用于动态加载由应用合并(Bundling)中代码切分阶段所生成的模块。该特性已得到除 IE11 以外的大部分浏览器的支持。开发人员可在任何时间无条件(例如,不同于只在模块头部定义导入,而是可在代码任何位置)使用 import() 方法异步导入以 moduleSpecifier = dir + 'my-math.mjs’方式动态构建的模块,并返回一个 Promise 对象。示例代码如下:

复制代码
const dir = './lib/';
const moduleSpecifier = dir + 'my-math.mjs';
async function loadConstant() {
const myMath = await import(moduleSpecifier);
const result = myMath.LIGHTSPEED;
assert.equal(result, 299792458);
return result;
}

import.meta 对象中包含了依赖于当前宿主环境的模块元数据。当前其中最受开发人员关注的是 url 属性,url 给出了当前模块文件的 URL 字符串。开发人员可使用该 URL 字符串去导入相关模块,或是根据模块当前信息有条件地执行一些操作。ES2020 提案中给出了如下示例代码,获取当前模块对应的 hamster.jpg 文件。

复制代码
(async () => {
const response = await fetch(new URL("../hamsters.jpg", import.meta.url));
const blob = await response.blob();
const size = import.meta.scriptElement.dataset.size || 300;
const image = new Image();
image.src = URL.createObjectURL(blob);
image.width = image.height = size;
document.body.appendChild(image);
})();

当该模块加载的时候,无论模块的加载位置在哪里,都会加载同级目录下的一个 hamsters.jpg 文件,并显示该图片。图片文件的大小可在导入时使用 JavaScript 元素设定,例如:

关键字 globalThis 支持开发人员在编写可移植 ECMAScript 代码时访问全局对象,无需根据浏览器、Worker 线程和 Node.js 环境分别使用 window、self 和 global,并支持对其它一些边缘情况的处理。

新的 export 语法(export * as ns from "mod)提供了新的 export from 方式,支持将另一个模块命名空间中的外来对象以命名的方式导出,提供类似于现有 export from 的使用方式。

Promise.allSettled() 的提出,完善了 ECMAScript ES2015 现有的 Promise.all() 和 Promise.race() 方法。该方法无论各 Promise 的返回结果是满足还是拒绝,都会执行设定的操作。示例代码如下:

复制代码
Promise.allSettled([
fetch("https://api.github.com/users/pawelgrzybek").then(data => data.json()),
fetch("https://api.github.com/users/danjordan").then(data => data.json())
])
.then(result => console.log(`All profile settled`));

在上例中如果使用标准的 Promise.all(),一旦第一个 Promise 被拒绝,那么整个 Promise 操作都会被拒绝,这样第二个 Promise 永远无法得到满足。Promise.allSettled 可处理需考虑部分执行结果的情况,例如一个 Promise 被拒绝,而另一个得到满足。

“可选链”( Optional chaining ,语法为“(a?.b)”)和“空位合并”( nullish coalescing ,语法为“(a ?? b)”)已得到 Babel(7.0 及以上版本)、Edge/Chrome/Firefox 等常用浏览器以及 TypeScript 3.7 以上版本的支持。两个特性支持在访问或调用值为空位的情况下执行短路操作。例如,let x = foo?.bar.baz() 语句可替代:

复制代码
let x = foo === null || foo === undefined ? undefined : foo.bar.baz();

BigInt 支持开发人员精确操作大型数值。创建 BigInt 时,需在整型值后添加 n,例如 10n,或是通过调用 BigInt() 方法。例如,2 ** 53 + 1 的求值结果为 9007199254740992,但该值是一个奇数,不可能以 2 为结尾,所以产生了错误。如果定义为 2n ** 53n +1n,那么就可正确求值为 9007199254740993n。这也是为什么 Twitter 的 JSON API 以字符串而非整型数值形式返回推文 ID 值的原因。部分最新版本浏览器已支持 BigInt ,其中包括 Firefox 68 和 Chrome 67 以上版本,其它一些浏览器正在着力解决中

String.matchAll 已得到除 Safari 外所有主要浏览器的支持。matchAll() 方法返回字符串匹配所有结果的迭代器,支持“捕获组”( capturing groups )等正则表达式,示例代码如下:

复制代码
const text = "From 2019.01.29 to 2019.01.30";
const regexp = /(?<year>\d{4}).(?<month>\d{2}).(?<day>\d{2})/gu;
const results = Array.from(text.matchAll(regexp));
// results:
// [
// [
// '2019.01.29',
// '2019',
// '01',
// '29',
// index: 5,
// input: 'From 2019.01.29 to 2019.01.30',
// groups: { year: '2019', month: '01', day: '29' }
// ],
// [ (...) ]
// ]

TC39 委员会由 JavaScript 开发人员、业界、学者等各方组成,与社区合作一并维护 JavaScript(即先前的 ECMAScript),并推进其发展。TC39 中包括了各主要浏览器厂商,每个 ECMAScript 特性提案将经历如下五个成熟度阶段,即阶段 0:“稻草人”(Strawman)阶段;阶段 1:提议阶段;阶段 2:草案阶段;阶段 3:候选阶段;阶段 4:完成阶段。达成阶段 4 的特性,将添加到标准中,并可安全使用。

ECMAScript 语言规范的首个版本于 1997 年发布,ECMAScript 2020 是该规范的第十一版。目前,ECMAScript 是全球范围内最广为使用的通用编程语言。

原文链接:

ES2020’s Feature Set Finalized

阅读数:1897 发布于:2020 年 4 月 14 日 12:34

评论

发布
暂无评论