正如我们所知,将任何非零数进行零次方得到1,因为n^0 = n^(a-a) = n^a / n^a = 1。
我刚刚注意到 JavaScript 实现(Chrome、Firefox、Edge、Safari)会简化此类操作,忽略第一个操作数并返回1. 然而,这些实现并不仅仅忽略第一个数字操作数,它们完全忽略任何东西!
console.log("hello" ** 0);
console.log(false ** 0);
console.log({} ** 0);
console.log(NaN ** 0);
console.log(null ** 0);
console.log(Infinity ** 0);Run Code Online (Sandbox Code Playgroud)
我的问题是:该行为是一种实现(意味着它可以随时更改),还是由 ECMA 某处描述?我搜索了 ECMA但没有找到任何内容
小智 2
如果指数为 0 ,求幂运算符不会忽略或短路基操作数。但是,指数是否等于 0 的检查在运算符的算法中发生得足够早,因此很难观察到边缘情况。要了解发生了什么,有必要查阅 ECMAScript 规范以了解**调用该运算符时会发生什么:
13.6 指数运算符
13.6.1 运行时语义:评估
求幂表达式 : 更新表达式 ** 求幂表达式
- 返回 ?EvaluateStringOrNumericBinaryExpression(UpdateExpression,**, ExponentiationExpression)。
抽象操作 EvaluateStringOrNumericBinaryExpression计算两个操作数并将它们传递给另一个抽象操作:
13.15.4 评估字符串或数字二进制表达式(左操作数、opText、右操作数)
- 令lref为leftOperand的计算结果。
- 让lval为 ? 获取值(lref)。
- 令rref为计算rightOperand的结果。
- 让rval为 ? 获取值(rref)。
- 返回 ?ApplyStringOrNumericBinaryOperator(lval,opText,rval)。
抽象操作ApplyStringOrNumericBinaryOperator采用二元运算符及其操作数,执行所需的类型强制并调用与该运算符关联的抽象操作:
13.15.3 应用字符串或数字二进制运算符(lval、opText、rval)
- 如果opText是
+,那么 [...]- 注意:此时必须是数值运算。
- 让lnum为 ? ToNumeric( lval ).
- 令rnum为 ? ToNumeric( rval ).
- [...]
- [...]
- 令操作为与下表中的opText和 Type( lnum )关联的抽象操作: [...]
- 返回操作(lnum,rnum)。
此时,基操作数被转换为数字。"hello"并{}成为NaN,false并null成为0,数字仍然是数字,BigInt 仍然是 BigInt。最后,如果opText为**且 Type( lnum ) 为 Number,则关联运算为 Number::exponentiate:
6.1.6.1.3 Number::exponentiate(底数,指数)
- 如果指数为 NaN,则返回 NaN。
- 如果指数为 +0 或指数为 -0,则返回 1。
因此,似乎无论基操作数是什么,如果指数为 0,该**运算符总是返回 1。如果不是 ApplyStringOrNumericBinaryOperator 的步骤 3,它就会返回 1。如果参数的类型为 Symbol,ToNumeric 会抛出 TypeError:
> Symbol() ** 0
Uncaught TypeError: Cannot convert a Symbol value to a number
Run Code Online (Sandbox Code Playgroud)
这表明,计算某个值的零次方不会忽略基操作数。
| 归档时间: |
|
| 查看次数: |
116 次 |
| 最近记录: |