Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the value of foo.x undefined in foo.x = foo = {n: 2}? [duplicate]

Tags:

This code:

var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};

Can you please explain what is meant by:

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

I see that {n:2} is assigned to foo. Why is undefined assigned to foo.x? Does foo = {n: 2}; return undefined?

like image 512
Nicolas S.Xu Avatar asked Jan 21 '16 20:01

Nicolas S.Xu


2 Answers

According to the spec, the left hand side of an assignment expression is evaluated first, even though the operator has right-to-left precedence. Thus the expression foo.x = foo = {n: 2} which is the same as foo.x = (foo = {n: 2}) is evaluated like this:

  1. Evaluate the left-hand expression foo.x to get a reference, which is where the value of the right-hand expression will be assigned to.

  2. Evaluate the right-hand expression, to to get the value that will be assigned. The right-hand side is another assignment expression, so it gets evaluated the same way:

    1. Evaluate foo to determine where to assign to.
    2. Evaluate the expression {n:2}, which creates an object, to determine the value to assign.
    3. Assign {n:2} to foo, and return {n:2}.

  3. Assign the value that the expression on the right-side evaluated to ({n:2}), to the reference that foo.x resolved to in step 1 (before foo was assigned a new value). Which is also the same as bar.x, because of the assignment bar = foo on the line before.

When this is done, the original object, that bar is still a reference to, will have an x property that references the second object created. foo is also a reference to that second object, so foo === bar.x.

like image 133
Paul Avatar answered Oct 21 '22 06:10

Paul


Because the property access foo.x on the left is evaluated before the right-hand side.

Let's make it more clear what your code actually does, by giving new names to the temporary expressions being evaluated:

var foo0 = {n: 1};
var foo1 = {n: 2};
foo0.x = foo1;
foo0 = foo1;
console.log(foo0.x);

Hence foo0.x is foo1.x is undefined.

In your original code, you can see that bar.x is {n: 2}, confirming this explanation.

like image 33
Nayuki Avatar answered Oct 21 '22 07:10

Nayuki