The internal reference value for a.x
— the "target" of the assignment a.x = a
— is calculated before the assignments happen. The target of the assignment is therefore the "x" property on the old value of a
, which is the same as b
. The new value of a
doesn't have an "x" property, so that's undefined. However, the assignment gave an "x" property to the old value of a
, which is the current value of b
.
If you like "language lawyering", you can see a description here in the ES2015 spec for the =
operator and how it works. Note that in step 1, something called lref is determined. That's the "target" I mentioned in the above paragraph, and note that it happens before the right-hand "assignment expression" is computed.