From EcmaScript standard:
11.4.4 Prefix Increment Operator
The production UnaryExpression : ++ UnaryExpression is evaluated as follows:
- Let expr be the result of evaluating UnaryExpression.
- Throw a SyntaxError exception if the following conditions are all true: �
- Type(expr) is Reference is true
- IsStrictReference(expr) is true
- Type(GetBase(expr)) is Environment Record
- GetReferencedName(expr) is either "eval" or "arguments"
- Let oldValue be ToNumber(GetValue(expr)).
- Let newValue be the result of adding the value 1 to oldValue, using the same rules as for the + operator (see 11.6.3).
- Call PutValue(expr, newValue).
- Return newValue.
and
11.13.2 Compound Assignment ( op= )
The production AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression, where AssignmentOperator is @= and @ represents one of the operators indicated above, is evaluated as follows:
- Let lref be the result of evaluating LeftHandSideExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating AssignmentExpression.
- Let rval be GetValue(rref).
- Let r be the result of applying operator @ to lval and rval.
- Throw a SyntaxError exception if the following conditions are all true:
- Type(lref) is Reference is true
- IsStrictReference(lref) is true
- Type(GetBase(lref)) is Environment Record
- GetReferencedName(lref) is either "eval" or "arguments"
- Call PutValue(lref, r)
Thus, var i = 0; i += ++i
is:
i = 0;
lvalue = value(i), which is 0;
rvalue = value(++i), which is: increment i, then value of i (1);
thus, rvalue = 1;
i = lvalue (0) + rvalue (1), which is 1.
Completely according to spec.
However, in C++, this is specifically defined to be undefined behaviour, thus on a different compiler you might also get 1. Or 99. Or it could set your computer on fire. All of those would be standard-compliant compilers. Thus, most people will recommend you only use pre/post-incremented variable once in a statement.