前言
ECMAScript 2015(ES6)新增内容很多,在 ES5 发布近 6 年(2009-11 至 2015-6)之后才将其标准化。两个发布版本之间时间跨度如此之大主要有两大原因:
- 比新版率先完成的特性,必须等待新版的完成才能发布。
- 那些需要花长时间完成的特性,也顶着很大的压力被纳入这一版本,因为如果推迟到下一版本发布意味着又要等很久,这种特性也会推迟新的发布版本。
因此,从 ECMAScript 2016(ES7)开始,版本发布将会变得更加频繁,每年发布一个新版本,这么一来新增内容也会更小。新版本将会包含每年截止时间之前完成的所有特性。
如何设计ECMAScript
TC39(推进 JavaScript 发展的委员会) 设计过程
每个 ECMAScript 特性的建议将会从阶段 0 开始, 然后经过下列几个成熟阶段。其中从一个阶段到下一个阶段必须经过 TC39 的批准。
阶段 0: Strawman 初稿
什么是 Strawman?
一个推进 ECMAScript 发展的自由形式的想法。该想法必须由 TC39 的会员提交,如果是非会员则必须注册成为 TC39 贡献者才能提交。
必备条件:
文件必须在 TC39 的会议上通过审议(原文),然后才能加入阶段 0 的建议页面。
什么是 Draft?草案是规范的第一个版本。其与最终标准中包含的特性不会有太大差别。
必备条件:建议此时必须要附加该特性的语法和语义的正式说明(使用 ECMAScript 标准的形式语言)。说明应该尽可能完善,但可以包含待办事项和占位符。该特性需要两个实验性的实现,其中一个可以在类似 Babel 的转译器(transpiler)中实现。
下一步:从该阶段开始只接受增量调整。
阶段 3:Candidate 候选
什么是 Candidate?候选阶段,建议基本完成,此时将从实现过程和用户使用两方面获取反馈来进一步完善建议。
必备条件:规范文档必须是完整的。指定的评审人(由 TC39 而不是带头人指定)和 ECMAScript 规范的编辑须在规范上签字。还有至少要两个符合规范的实现(不必指定默认实现)。
下一步:此后,只有在实现和使用过程中出现了重大问题才会修改建议。
阶段 4:Finished 完成
什么是 Finished?建议已经准备就绪,可以添加到标准之中。
必备条件:建议进入完成阶段之前需要满足以下几点:
- Test 262 的验收测试(基本上都是 JavaScript 写的用来验证语言特性的单元测试)。
- 两个通过测试的符合规范的实现。
- 特性实现相关的重要实践经验。
- ECMAScript 规范的编辑在规范文本上的签字。
下一步: 建议将会尽快加入 ECMAScript 规范之中。当规范通过年度审核成为标准,该建议也正式成为标准的一部分。
ECMAScript 2016新增特性
已被纳入 ES2016 的特性
- Array.prototype.includes
- 指数运算符
1、Array.prototype.includes
Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
如果传入的值在当前数组(this)中则返回 true,否则返回 false
includes方法与 indexOf 方法很相似 下面两个表达式是等价的:
arr.includes(x)
arr.indexOf(x) >= 0
唯一的区别是 includes() 方法能找到 NaN,而 indexOf() 不行:
[NaN].includes(NaN)
true
[NaN].indexOf(NaN)
-1
includes 不会区分 +0 和 -0(这也与其他 JavaScript 特性表现一致):
[-0].includes(+0)
true
- 为什么方法取名
includes
而不是contains
? 后者是最初的选择,但在 web 上将会破坏已有的代码(MooTools 在Array.prototype
上添加了 contains 方法)。 - 为什么方法取名
includes
而不是has
? has 通常用于键(Map.prototype.has),includes 通常用于元素(String.prototype.includes)。集合中的元素既可以被看当做 键 也可被当做 值,所以才有 Set.prototype.has (而不是 includes)。 - ES6 的
String.prototype.includes
方法可用于字符串,而不能用于字符。这是否和Array.prototype.includes
不一致? 如果数组和字符串的 includes 方法是相同的工作机制,那么数组的 includes 方法就应该接受数组,而不是数组元素了。不过这两个 includes 方法都参考了 indexOf 方法;字符一般是特殊情况,而任意长度的字符串则更常见。
2、指数运算符
新提出来的特性是将 ** 作为指数操作的中缀运算符:
2 ** 2 // 4
2 ** 3 // 8
这个运算符的一个特点是右结合,而不是常见的左结合。多个指数运算符连用时,是从最右边开始计算的。
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512
上面代码中,首先计算的是第二个指数运算符,而不是第一个。
指数运算符可以与等号结合,形成一个新的赋值运算符(**=)。
let a = 1.5;
a **= 2;
// 等同于 a = a * a;
let b = 4;
b **= 3;
// 等同于 b = b * b * b;
注意,V8 引擎的指数运算符与Math.pow
的实现不相同,对于特别大的运算结果,两者会有细微的差异。
99**99
3.697296376497268e+197
Math.pow(99,99)
3.697296376497263e+197