[关闭]
@zhouweicsu 2015-12-07T10:25:48.000000Z 字数 5756 阅读 931

【译】ECMAScript 2016 (ES7) 新特性一览

翻译


作者:Dr. Axel Rauschmayer,时间:2015-11-15

原文链接: http://www.2ality.com/2015/11/tc39-process.html

译文链接: http://zhouweicsu.github.io/mobile/2015/12/04/tc39-process/

本文回答了关于下一版 JavaScript(ECMAScript 2016)的以下几个问题:

本文会持续更新以及时反馈最新进展。

1、谁在设计 ECMAScript?

答:TC39 (Technical Committee 39)。

TC39 是推进 JavaScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席。会议纪录都可在网上查看,可以让你对 TC39 如何工作有一个清晰的概念。

有时候(实际上本文就如此),你会发现 TC39 会员这个词被用来指代一个人,其实指的是 TC39 会员公司派出的代表。

很有意思的是,TC39 实行的是协商一致的原则:通过一项决议必须得到每一位会员(公司代表)的赞成。

2、如何设计 ECMAScript?

2.1 问题:ECMAScript 2015 (ES6) 这个版本太大了

最近发布的 ECMAScript(ES6)新增内容很多,在 ES5 发布近 6 年(2009-11 至 2015-6)之后才将其标准化。两个发布版本之间时间跨度如此之大主要有两大原因:

因此,从 ECMAScript 2016(ES7)开始,版本发布将会变得更加频繁,每年发布一个新版本,这么一来新增内容也会更小。新版本将会包含每年截止时间之前完成的所有特性。

2.2 解决方案: TC39 设计过程

每个 ECMAScript 特性的建议将会从阶段 0 开始, 然后经过下列几个成熟阶段。其中从一个阶段到下一个阶段必须经过 TC39 的批准。

阶段 0: Strawman 初稿

什么是 Strawman?一个推进 ECMAScript 发展的自由形式的想法。该想法必须由 TC39 的会员提交,如果是非会员则必须注册成为 TC39 贡献者才能提交。

必备条件:文件必须在 TC39 的会议上通过审议(原文),然后才能加入阶段 0 的建议页面

阶段 1:Proposal 建议

什么是 Proposal?一份新特性的正式建议文档。

必备条件:必须确定一位带头人来为负责这份建议。无论是带头人或者联合带头人都必须是 TC39 的会员(原文)。建议要解决的问题必须以简明的文字描述,而解决方案则要给出相应的实例和 API,并详细描述语义及算法。最后,必须指明此建议的潜在问题,例如与其他特性之间的关联,实现难点等。实现方式,polyfills 和 demo 也是需要的。

下一步:通过一个阶段 1 的建议,表明 TC39 愿意研究、讨论并促成该建议。接下来,我们就可以期待该建议的重大改变了。

阶段 2:Draft 草案

什么是 Draft?草案是规范的第一个版本。其与最终标准中包含的特性不会有太大差别。

必备条件:建议此时必须要附加该特性的语法和语义的正式说明(使用 ECMAScript 标准的形式语言)。说明应该尽可能完善,但可以包含待办事项和占位符。该特性需要两个实验性的实现,其中一个可以在类似 Babel 的转译器(transpiler)中实现。

下一步:从该阶段开始只接受增量调整。

阶段 3:Candidate 候选

什么是 Candidate?候选阶段,建议基本完成,此时将从实现过程和用户使用两方面获取反馈来进一步完善建议。

必备条件:规范文档必须是完整的。指定的评审人(由 TC39 而不是带头人指定)和 ECMAScript 规范的编辑须在规范上签字。还有至少要两个符合规范的实现(不必指定默认实现)。

下一步:此后,只有在实现和使用过程中出现了重大问题才会修改建议。

阶段 4:Finished 完成

什么是 Finished?建议已经准备就绪,可以添加到标准之中。

必备条件:建议进入完成阶段之前需要满足以下几点:

下一步: 建议将会尽快加入 ECMAScript 规范之中。当规范通过年度审核成为标准,该建议也正式成为标准的一部分。

3、别把它们称做 ECMASript 20xx 特性

综上所述,只有建议进入阶段 4,你才能确定这个特性会被纳入标准之中。因为此时它很有可能被加入到下一版本的 ECMAScript,但也不是 100% 确定(因为有可能会花更长时间)。因此,你不能称这个建议为“ES7 特性”或“ES2016 特性”。所以我喜欢把文章或博客的标题写成这样:

如果建议处于阶段 4,我觉得称它 ES20xx 特性是 OK 的,但还是等规范的编辑确认该特性将会加入哪个版本之后才最保险。例如 Object.observe 就是一个已经进入阶段 2 ,却最终被撤回的 ECMAScript 建议。

4、ECMAScript 2016 将会有什么特性?

已被纳入 ES2016 的特性:

以下处于阶段 4 的特性将可能会纳入 ES2016:

以下处于阶段 3 的特性也许会纳入 ES2016:

如果你不知道某个建议特性处于哪个阶段,你可以在 ECMA-262 GitHub 库的 readme 中查阅。

5、Array.prototype.includes (Domenic Denicola, Rick Waldron)

数组的 includes 方法有如下签名:

  1. Array.prototype.includesvalue:任意值): boolean

如果传入的值在当前数组(this)中则返回 true,否则返回 false:

  1. > ['a', 'b', 'c'].includes('a')
  2. true
  3. > ['a', 'b', 'c'].includes('d')
  4. false

includes 方法与 indexOf 方法很相似——下面两个表达式是等价的:

  1. arr.includes(x)
  2. arr.indexOf(x) >= 0

唯一的区别是 includes() 方法能找到 NaN,而 indexOf() 不行:

  1. > [NaN].includes(NaN)
  2. true
  3. > [NaN].indexOf(NaN)
  4. -1

includes 不会区分 +0-0 (这也与其他 JavaScript 特性表现一致):

  1. > [-0].includes(+0)
  2. true

类型数组也有 includes() 方法:

Typed Arrays will also have a method includes():

  1. let tarr = Uint8Array.of(12, 5, 3);
  2. console.log(tarr.includes(5)); // true

5.1 常见问题

5.2 扩展阅读

6、指数运算符(Rick Waldron)

新提出来的特性是将 ** 作为指数操作的中缀运算符:

  1. x ** y

与以下表达式运算结果相同:

  1. Math.pow(x, y)

示例:

  1. let squared = 3 ** 2; // 9
  2. let num = 3;
  3. num **= 2;
  4. console.log(num); // 9

扩展阅读:

7、SIMD.JS – SIMD APIs + polyfill (John McCutchan, Peter Jensen, Dan Gohman, Daniel Ehrenberg)

SIMD 意思是“single instruction, multiple data(单指令流多数据流)”,CPU 可以通过单条指令操作一组数据(而不是仅操作单一值),SIMD 指令集最有名的一个例子就是由 Intel 处理器的 SSE(Streaming SIMD Extensions)

下面是简短的示例代码,请参考后面源码获取更多信息。

  1. var a = SIMD.float32x4(1.0, 2.0, 3.0, 4.0);
  2. var b = SIMD.float32x4(5.0, 6.0, 7.0, 8.0);
  3. var c = SIMD.float32x4.add(a,b);

扩展阅读:

8、异步函数(Brian Terlson)

在我介绍异步函数之前,我会先介绍如何通过 Promises 和 generators 来使用看起来同步的代码去执行异步操作。

8.1 用 Promises 和 generators 编写异步代码

对于需要异步地计算一次性结果的函数来说,Promises(ES6 的一部分)现在越来越流行。一个例子就是客户端 fetch API,它是一种替代 XMLHttpRequest 检索文件的方案。代码如下:

  1. function fetchJson(url) {
  2. return fetch(url)
  3. .then(request => request.text())
  4. .then(text => {
  5. return JSON.parse(text);
  6. })
  7. .catch(error => {
  8. console.log(`ERROR: ${error.stack}`);
  9. });
  10. }
  11. fetchJson('http://example.com/some_file.json')
  12. .then(obj => console.log(obj));

co 是一个使用了 Promises 和 generators 让编程风格看起来更像异步的库,但也需要使用类似于前一个例子的风格去编码:

  1. const fetchJson = co(function* () {
  2. try {
  3. let request = yield fetch(url);
  4. let text = yield request.text();
  5. return JSON.parse(text);
  6. }
  7. catch (error) {
  8. console.log(`ERROR: ${error.stack}`);
  9. }
  10. });

每次回调函数(一个 generator 函数!)产生一个 Promise 给 co,回调函数就会被挂起。一旦这个 Promise 完成,co 就会恢复该回调函数:如果 Promise 被实现,yield 会返回这个实现的值,如果被拒绝,则 yield 会抛出异常。另外,co 能处理回调函数返回的结果(与 then() 相似)。

8.2 异步函数

异步函数的语法基本上可以说是实现了 co 所做的:

  1. async function fetchJson(url) {
  2. try {
  3. let request = await fetch(url);
  4. let text = await request.text();
  5. return JSON.parse(text);
  6. }
  7. catch (error) {
  8. console.log(`ERROR: ${error.stack}`);
  9. }
  10. }

在内部,异步函数的工作非常类似于 generators,但它并不会被翻译为 generator 函数。

8.3 变体

异步函数有以下几种变体:

函数声明: async function foo() { }
函数表达式:const foo = async function () {};
方法定义:let obj = { async foo() {} }
箭头函数:const foo = async () => {}

8.4.扩展阅读

9、扩展阅读

下面是本篇博客的重要参考资料:

其他资料:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注