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

L'exception JavaScript "unparenthesized unary expression can't appear on the left-hand side of '**'" se produit lorsqu'un opérateur unaire (parmi typeof, void, delete, await, !, ~, +, -) est utilisé sur l'opérande gauche de l'opérateur d'exponentiation sans parenthèse.

Message

SyntaxError: Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence (moteur JavaScript basé sur V8)
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)

Type d'erreur

Quel est le problème ?

Cela provient vraisemblablement d'une écriture comme celle-ci :

js
-a ** b

Ici, l'expression est ambigüe et on ne sait pas si elle devrait être évaluée comme (-a) ** b ou comme -(a ** b). En mathématiques, l'écriture -x2 signifie -(x ** 2), et c'est ainsi que de nombreux langages de programmation, comme Python, Haskell, et PHP, gèrent cette évaluation. Mais si la précédence de l'opérateur unaire moins l'emporte sur **, cela casse la symétrie avec a ** -b, qui s'évalue sans ambigüité comme a ** (-b). Aussi, le langage interdit cette syntaxe et impose d'utiliser des parenthèses d'un côté ou de l'autre pour résoudre l'ambigüité.

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

D'autres opérateurs unaires ne peuvent pas être utilisés sur l'opérande gauche non plus.

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

Exemples

Lorsqu'on écrit des expressions mathématiques complexes utilisant l'exponentiation, on peut aboutir à quelque chose comme :

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 '**'
}

Toutefois, le fragment -1 ** n est illégal en JavaScript. À la place, on utilisera des parenthèses sur l'opérande gauche :

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

Cela a également l'avantage de rendre le code plus compréhensible et explicite.

Voir aussi