Here is a compound expression containing two assignment operators:
var a = {n: 1};
var b = a;
a.x = a = {m: 2};
a; // => {m: 2}
b; // => {n: 1, x: {m: 2}}
The tricky part is the third line:
a.x = a = {m: 2};
IMHO, The assignment operator =
is right-associative, so the nesting structure of the expression is:
a.x = (a = {m: 2});
But the evaluation order in ES5 is always from left to right, according to ES5 Annex D.
According to ES5 Section 11.13.1,
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:
- Let lref be the result of evaluating LeftHandSideExpression.
- Let rref be the result of evaluating AssignmentExpression.
- Let rval be GetValue(rref).
- Throw a SyntaxError exception if the following conditions are all true: ....omitted intentionally to save space
- PutValue(lref, rval).
- Return rval.
So my understanding of the left-to-right evaluation order is :
- evaluate
a.x
first and return a referencelref1
for it evaluate
a = {m: 2}
to obtainrref1
, because it is also an assignment expression, we'll start the procedure again (like recursion)2.1. evaluate
a
first and return a referencelref2
for it2.2. evaluate
{m: 2}
and return the very object{m: 2}
asrref2
2.3. Let
rval2
=GetValue(rref2)
, sorval2
is also the object{m: 2}
2.4.
PutValue(lref2, rval2)
, soa
will rebinds the object{m: 2}
instead of{n: 1}
2.5. return
rval2
, i.e. the object{m: 2}
asrref1
(not Reference type, but object)Let
rval1
=GetValue(rref1)
, which is also the very object{m: 2}
PutValue(lref1, rval1)
, so the memory address whichlref1
refers to will be{m: 2}
. Andb.x
still refers to this address andb
will be updated.
This procedure complies to the ES5 Spec and explains the result well.
My questions are:
Is this evaluation order abovementioned true or false? If false, any alternative explanations?
How to understand the Reference Specification Type in ES5 appropriately? Is it just an intermediate pointer which refers to certain memory address?