This is because when you write
var foo = {};
foo.x = foo = {n: b} //a=b=c
while the line is being executed, foo is pointing to {}
but when this statement is broken down to
foo.x = (foo = {n: b}) /a=(b=c)
foo's reference has changed from {}
to {n:b}
but foo
in foo.x
(a) is still pointing to old reference of foo
since left hand expression was evaluated before assignment had begun.
As per the spec
If LeftHandSideExpression is neither an ObjectLiteral nor an
ArrayLiteral,
a. then Let lref be the result of evaluating
LeftHandSideExpression.
Which means before the assignment foo.x
was still having reference to old foo
.
So, if you tweak your example a little bit by doing
var foo = {z:2};
foo.x = foo.n = {n: 1};
In this example, you didn't change the reference to foo
, only assigned new property, so the output now is
Object {z: 2, n: Object, x: Object}
Now, it has retained the reference to old foo
since a new reference was not assigned hence all properties z
, n
and x
are being retained.