SyntaxError: unparenthesized unary expression can't appear on the left-hand side of '**'

当一元运算符(typeofvoiddeleteawait!~+- 之一)在没有括号的情况下用作幂运算符的左操作数时,JavaScript 会抛出“未加括号的一元表达式不能出现在‘**’的左侧”异常。

消息

SyntaxError: Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence (V8-based)
SyntaxError: unparenthesized unary expression can't appear on the left-hand side of '**' (Firefox)
SyntaxError: Unexpected token '**'. Ambiguous unary expression in the left hand side of the exponentiation expression; parentheses must be used to disambiguate the expression. (Safari)

错误类型

SyntaxError

哪里出错了?

你可能写了类似这样的代码:

js
-a ** b

它应该被评估为 (-a) ** b 还是 -(a ** b) 是模棱两可的。在数学中,-x2 表示 -(x ** 2)——许多语言(包括 Python、Haskell 和 PHP)都是这样处理的。但是,让一元减号运算符优先于 ** 会破坏与 a ** -b 的对称性,而 a ** -b 明确表示 a ** (-b)。因此,该语言禁止这种语法,并要求你用括号括起来以解决歧义。

js
(-a) ** b
-(a ** b)

其他一元运算符也不能作为幂运算符的左侧。

js
await a ** b
!a ** b
+a ** b
~a ** b

示例

在编写涉及幂运算的复杂数学表达式时,你可能会写类似这样的代码:

js
function taylorSin(x) {
  return (n) => (-1 ** n * x ** (2 * n + 1)) / factorial(2 * n + 1);
  // SyntaxError: unparenthesized unary expression can't appear on the left-hand side of '**'
}

然而,-1 ** n 部分在 JavaScript 中是非法的。相反,应该将左操作数用括号括起来:

js
function taylorSin(x) {
  return (n) => ((-1) ** n * x ** (2 * n + 1)) / factorial(2 * n + 1);
}

这也能让代码的意图对其他阅读者来说更清晰。

另见