According to Ecma-262, prefix increment and decrement operators are defined as:
UpdateExpression :
LeftHandSideExpression ++
LeftHandSideExpression ‐‐
++ UnaryExpression
‐‐ UnaryExpression
This is surprising, both that the postfix and prefix operators are defined in the same rule, and that it's ++ UnaryExpression
when surely a unary expression in general is not actually a valid argument for the update operators.
It would seem cleaner and more logical to define the prefix increment and decrement operators in UnaryExpression
itself, along with the other prefix operators, and other C syntax languages do this, e.g. the C standard section 6.5.3 defines unary-expression
to include the prefix update operators along with the others.
Why does JavaScript define these operators the way it does?
Why does JavaScript define these operators the way it does?
It's mostly historical, as so many other oddities in the spec.
It would seem cleaner and more logical to define the prefix increment and decrement operators in
UnaryExpression
itself, along with the other prefix operators, and other C syntax languages do this
In fact, that's how it was defined for many years, in ES5.1 and ES6. It's simple, and has one syntactic production per precedence level (PostfixExpression
being the next-tighter one), and was probably directly inherited from the C or Java grammar when JS was conceived.
Surely a unary expression in general is not actually a valid argument for the update operators
In C, -- -- x
is actually valid, so that's why the prefix increment and decrement operator expressions contain another UnaryExpression
. Of course, it would throw an exception when trying to evaluate the expression, but parsing it would work fine in ES5.
ES6 then added the concept of early errors, and increment and decrement operations now required a valid assignment target expression upon parsing. This was not encoded in the syntactical productions though.
It is surprising that the postfix and prefix operators are defined in the same rule
This definition is new in ES7. It changed with this commit that introduced the exponentiation operator, where the PostfixExpression
was renamed to UpdateExpression
and the prefix operators were moved into the rule. Some change like that was necessary because the **
operator allows an update expression, but not a UnaryExpression
as its first argument (because unary minus, as in -x ** 3
, was deemed too ambiguous).