Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chained assignment and circular reference in JavaScript

Tags:

javascript

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?

like image 311
antoine129 Avatar asked Aug 07 '15 15:08

antoine129


2 Answers

When executing the assignment operator, JS evaluates the left part first. So this

foo.bar = foo = {n: 2};

is interpreted as

  1. evaluate foo.bar. This returns a reference {base: Object {n:1}, property:bar}.

  2. 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}

  3. 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>")
like image 77
georg Avatar answered Sep 22 '22 13:09

georg


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
like image 37
Daniel A. White Avatar answered Sep 20 '22 13:09

Daniel A. White