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?
Yes, your understanding about the operator order appears to be correct.
ECMAScript 5 section 8.7 says:
The process of creating a reference from property access is defined in 11.2.1:
Thus the reference
lref1
holds the object value ofa
(along with the referenced name string"x"
), which you originally created with{n: 1}
. A reference does not care about the variable that it came from; it cares only about what base value and reference name it is supplied when created.Altering what value is held by
a
has no effect whatsoever on the base value held by the referencelref1
.lref1
continues to the hold the original value ofa
(i.e., that{n: 1}
object) regardless of whata
does after the creation oflref1
.In short, the reference created from the expression
a.x
ceases to have anything to do with the variablea
as soon as the reference is created. Instead, the reference knows only about the value that was held bya
at the time the reference was created.