ECMAScript6 的开发花费了四年之久,之后TC-39决定缩短开发周期,采用年度周期来发布语言的新特性,以确保语言的迭代速率与性能的快速发展。
由于开发周期的缩短,可想而知的是此后每个新的ES版本拥有的新特性会比从ES5时代变到ES6时代时少许多。为了标识这种新的变化,新版本号不再重点描述版本的数字代号,而是改为指明规范发布的年份,因此,ES6也被称为ES2015,而ES7也正式被命名为ES2016。TC-39小组决定将来所有的ES版本都采用如上的年份命名规则。
ES2016(ES7)于2016年3月定稿,并且只向语言添加了三项内容:
一、一个新的数学运算符
二、一个新的数组方法
三、一种新的语法错误
新特性一、幂运算符
1.幂运算符的符号
幂运算符是两个星号(**),其左侧是底数,右侧则是指数,
ex: let res = 10 ** 2;
console.log(res); //100
console.log( res === Math.pow(10,2) ); //true
使用Math.pow()能获得相同的结果,但显然运算符比方法显得更为直观。
2.幂运算符的优先级
幂运算符的优先级在JavaScript的二元运算符中是最高的(但低于一元运算符)。
ex:let res = 5 * 10 ** 2;
console.log(res); //500
会首先计算幂,再与5相乘来产生最终结果500
3.幂运算符操作数的限制
幂运算符有一个稍显独特的限制: 运算符左侧不能是除了 ++ 或 -- 之外的任意一元表达式,
ex:let res = -5 ** 2; // 语法错误
因为 -(负号运算符)的二义性,程序会产生语法错误,因为 - 可以是 -5 也可以是 -25,如果想要消除-运算符的二义性,需要额外添加括号,
ex:let res1 = - (5 ** 2); // 等于 -25
let res2 = (-5) ** 2; // 等于 25
若为幂运算表达式包裹括号,那么 - 会作用在这整个表达式上;而若你为 -5 包裹括
号,则清楚表示想要获取 -5 的二次幂。
在幂运算符的左侧表达式使用的是 ++ 或 -- 时,就无需使用括号,因为这两个运算符在操作数上的行为都被清晰定义了: ++ 或 -- 作为前缀会在其他任意运算发生之前修改操作数,而作为后缀则会在整个表达式计算完毕后才修改操作数。在幂运算符左侧的这两种用法都是安全的,正如下面代码所示:
let n = 2,
m = 2;
console.log(++n ** 2); // 9
console.log(n); // 3
console.log(m-- ** 2); // 4
console.log(m); // 1
此例中的 n 在幂运算符被运用之前就已被递增,因此 n 会变为 3 ,并且幂运算的结果为 9 。而对于m 来说,在参与幂运算时它的值仍然保持为 2 ,在运算之后才被递减到1 。
新特性二、Array.prototype.includes() 方法
Array.prototype.includes() 方法接受两个参数:需要搜索的值、可选的搜索起始位置索引。当提供了第二个参数时, includes() 会从该位置开始尝试匹配(默认的起始位置为 0 )。若在数组中找到了该值,返回 true; 否则返回 false 。
ex: let vals = [1,2,3];
console.log(vals.includes(1)); //true
console.log(vals.includes(0)); //false
//从索引2开始搜索
console.log(vals.includes(1,2)); //false
此处使用 1 去调用 vals.includes() 返回了 true ,而使用 0 则会返回 false ,因为0 并不在此数组中。当使用了第二个参数让搜索从索引位置 2 (该位置的元素值是 3 )开始进行时, vals.includes() 方法返回了 false ,因为数值 1 并不存在于位置 2 与数组末端之间。
includes() 方法使用 === 运算符来进行值比较,仅有一个例外: NaN 被认为与自身相等,尽管 NaN === NaN 的计算结果为 false 。这与 indexOf() 方法的行为不同,后者在比较时严格使用了 === 运算符。为了明白其中的差异,研究如下代码:
let vals = [1, NaN, 2];
console.log(vals.indexOf(NaN)); // -1
console.log(vals.includes(NaN)); // true
vals.indexOf() 方法为 NaN 返回了 -1 ,尽管 NaN 实际上被包含在 vals 数组中。
另一方面,由于使用不同的比较运算符, vals.includes() 方法则为 NaN 返回了 true。
在实现中的另一个怪异点是 +0 和 -0 被认为是相等的。在这个方面, indexOf() 与includes() 行为一致:
let vals = [1, +0, 2];
console.log(vals.indexOf(-0)); // 1
console.log(vals.includes(-0)); // true
此处的 indexOf() 与 includes() 都在传入 -0 的时候找到了 +0 ,因为它们认为这两个值是相等的。注意这与 Object.is() 方法的行为有差异,后者认为 +0 与 -0 是不同的值。
新特性三、函数作用域严格模式改动
ES2016 规定如果函数的参数被进行解构或是拥有默认值,则在该函数内部使用 "use strict" 指令将是违法的。当函数体内出现了 "use strict" 时,该函数只允许使用简单参数列表(也就是所包含的参数没有进行解构,也没有默认值)。
ex:
// 没有问题,使用了简单参数列表
function okay(first, second) {
"use strict";
return first;
}
// 语法错误
function notOkay1(first, second=first) {
"use strict";
return first;
}
// 语法错误
function notOkay2({ first, second }) {
"use strict";
return first;
}
你依旧可以在只有简单参数列表的函数内使用 "use strict" ,这也是 okay() 函数如预期正常工作的原因(就像在 ES5 中一样)。 notOkay1() 函数则会有语法错误,因为它使用了参数的默认值。类似的, notOkay2() 函数同样有语法错误,因为它使用了解构参数。