I've been coding for years and suddenly stuck to some simple thing about operators precedence in case of increment/decrement operators.
According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence the postfix increment/decrement has higher priority than the prefix one. So, I expect that in expression
x = --a + a++;
the increment will be calculated first and only after that the decrement.
But, in tests this expression calculates left-to-right like that operators have the same priority. And as result
a=1;x = --a + a++
equals to 0 instead of 2.
Ok. Assuming that prefix/postfix operators have the same precedence, I try to reorder it with parentheses:
a=1;x = --a + ( a++ )
But again, the result will be 0 and not 2 as I expected.
Can someone explain that please? why parentheses here do not affect anything? How can I see that postfix has higher precedence than prefix?
Operator precedence is not the same thing as evaluation order.
Operator precedence tells you that
f() + g() * h()
is parsed as
f() + (g() * h())
(because *
has higher precedence than +
), but not which function is called first. That is controlled by evaluation order, which in JavaScript is always left-to-right.
Parentheses only override precedence (i.e. they affect how subexpressions are grouped), not order of evaluation:
(f() + g()) * h()
performs addition before multiplication, but in all cases f
is called first and h
last.
In your example
--a + a++
the relative precedence of prefix --
and postfix ++
doesn't matter because they're not attached to the same operand. Infix +
has much lower precedence, so this expression parses as
(--a) + (a++)
As always, JS expressions are evaluated from left to right, so --a
is done first.
If you had written
--a++
that would have been parsed as
--(a++)
(and not (--a)++
) because postfix ++
has higher precedence, but the difference doesn't matter here because either version is an error: You can't increment/decrement the result of another increment/decrement operation.
However, in the operator precedence table you can see that all prefix operators have the same precedence, so we can show an alternative:
// ! has the same precedence as prefix ++
!a++
is valid code because it parses as !(a++)
due to postfix ++
having higher precedence than !
. If it didn't, it would be interpreted as (!a)++
, which is an error.