According to the JavaScript spec, left hand side is always evaluated first:
12.14.4 Runtime Semantics: Evaluation
AssignmentExpression[In, Yield] : LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
1. Let lref be the result of evaluating LeftHandSideExpression.
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-assignment-operators-runtime-semantics-evaluation
It can be clearly seen if you add another reference to the foo
object:
var ref = {n:1};
var foo = ref;
var bar = foo;
foo.x = foo = {n: 2};
ref.x
exists because foo.x
refers to the unmodified value of foo
.