幂运算符(**)

ECMAScript 幂运算符(**) 由 Rick Waldron 负责。目前已经进入 stage 4, 幂运算符(**) 是 ECMAScript 2016(ES7) 的一部分。

1. 概述

幂运算符返回第一个操作数做底数,第二个操作数做指数的乘方。即,xy,其中 xy 是其两个操作数。

幂运算符是右结合的。a ** b ** c 等同于 a ** (b ** c)

2. 语法

x ** y

3. 注解

在大多数编程语言,比如 PHP 或 Python 等中,都包含幂运算符(一般来说符号是 ^ 或者 **)。

这些语言中的幂运算符有着比其他的单目运算符(如一元 + 或一元 - )更高的优先级。但是作为例外,在 Bash 中,** 运算符被设计为比单目运算符优先级更低。

在最新的 JavaScript ES2016(ES7) 中,禁止使用带歧义的幂运算表达式。比如,底数前不能紧跟一元运算符(+/-/~/!/delete/void/typeof

-2 ** 2;
+2 ** 2;
~2 ** 2;
!2 ** 2;
delete 2 ** 2;
void 2 ** 2;
typeof 2 ** 2;
// SyntaxError: Unexpected token **

-(2 ** 2); // -4
+(2 ** 2); // 4
~(2 ** 2); // -5
(~2) ** 2; // -5
!2 ** 2; // 9
delete (2 ** 2); // true
(delete 2) ** 2; // 1
void (2 ** 2); // undefined
(void 2) ** 2; // NaN
typeof (2 ** 2); // "number"
(typeof 2) ** 2; // NaN

2 ** -2; // 0.25

4. 其它示例

2 ** 3 ** 2     // 512
2 ** (3 ** 2) // 512
(2 ** 3) ** 2 // 64

Infinity ** -Infinity; // 0
(-2) ** (0.2); // NaN

5. Math.pow()

x ** y 等价于 Math.pow(x, y)。但是在之前的 V8 引擎实现时有一个 bug,导致两者并不总是相等,比如:Math.pow(99,99) 的结果是 3.697296376497263e+197,但是 99**99 的结果是 3.697296376497268e+197

两者并不相等:

3.697296376497263e+197
3.697296376497268e+197

截至目前(2018-02-11)在最新版 Chrome 66(V8 6.6.43)中这个 bug 依然没有修复。关于这个 bug 的详细情况可以参考我之前的文章 V8 使用“常量折叠”优化技巧,导致幂(**)运算有时候不等于 Math.pow()

6. Math.pow() 特殊值处理

返回 xy 次方的依赖于实现的近似值 .

  • yNaN, 返回结果是 NaN.
  • y+0, 返回结果是 1, 即使 xNaN.
  • y−0, 返回结果是 1, 即使 xNaN.
  • xNaNy 是非零 , 返回结果是 NaN.
  • abs(x)>1y+∞, 返回结果是 +∞.
  • abs(x)>1y−∞, 返回结果是 +0.
  • abs(x)==1y+∞, 返回结果是 NaN.
  • abs(x)==1y−∞, 返回结果是 NaN.
  • abs(x)<1y+∞, 返回结果是 +0.
  • abs(x)<1y−∞, 返回结果是 +∞.
  • x+∞y>0, 返回结果是 +∞.
  • x+∞y<0, 返回结果是 +0.
  • x−∞y>0y 是奇数 , 返回结果是 −∞.
  • x−∞y>0y 不是奇数 , 返回结果是 +∞.
  • x−∞y<0y 是奇数 , 返回结果是 −0.
  • x−∞y<0y 不是奇数 , 返回结果是 +0.
  • x+0y>0, 返回结果是 +0.
  • x+0y<0, 返回结果是 +∞.
  • x−0y>0y 是奇数, 返回结果是 −0.
  • x−0y>0y 不是奇数, 返回结果是 +0.
  • x−0y<0y 是奇数, 返回结果是 −∞.
  • x−0y<0y 不是奇数, 返回结果是 +∞.
  • x<0x 是有限的, 且 y 是有限的, 且 y 不是整数 , 返回结果是 NaN.

7. 实现