Consider the following statements:
var foo = {n: 1};
foo.bar = foo = {n: 2};
Can you explain why foo.bar
is undefined
instead of being foo
?
When executing the assignment operator, JS evaluates the left part first. So this
foo.bar = foo = {n: 2};
is interpreted as
evaluate foo.bar
. This returns a reference {base: Object {n:1}, property:bar}
.
then evaluate the second assignment:
2.1 eval foo
. This returns a reference {base:<scope>, property:foo}
2.2. eval {n:2}
. This creates a new object.
2.3 put value: <scope>.foo = {n:2}
2.4 return {n:2}
put value to the first reference: {n:1}.bar = {n:2}
. This runs fine, but the old object {n:1}
is not accessible anymore, since <scope>.foo
already refers to the new object
Details: http://ecma-international.org/ecma-262/5.1/#sec-11.13.1
If you make a copy of foo
before, you'll see that the leftmost =
actually modifies the old object:
var foo = {n:1};
var oldFoo = foo;
foo.bar = foo = {n: 2};
document.write(JSON.stringify(foo) + "<br>")
document.write(JSON.stringify(oldFoo) + "<br>")
So by the time the assignment for foo.bar
happens, the reference is "filled in" for foo
. which makes it the original object.
Let's expand your code a bit to make it more clear.
var foo1, foo2;
foo1 = foo2 = {n:1};
foo1 === foo2; // true
foo1.bar = foo1 = {n:2}
foo1.bar === foo2; // false
foo1 === foo2; // false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With