JavaScript code trick: What's the value of foo.x

JavascriptObjectVariable Assignment

Javascript Problem Overview


I found this problem in a GitHub front-end interview questions collection:

> var foo = {n: 1}; > var bar = foo; > foo.x = foo = {n: 2}; > >Question: What is the value of foo.x?

The answer is undefined.

I've done some research and what I understand this problem is (correct me if I'm wrong):

  • var foo = {n: 1}; declares an object foo which has property n equal to 1.
  • var bar = foo; declares an object bar which refers to the same object as foo.
  • foo.x = foo = {n: 2}; which I believe is equal to foo.x = (foo = {n: 2});
  • And then I got foo.x equals to undefined. However, the value of bar.x is the object {n:2}.

If bar and foo refer to same object, why did bar.x get a value while foo.x is undefined? What is really happening in foo.x = foo = {n: 2};?

Javascript Solutions


Solution 1 - Javascript

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

determines that foo.x refers to a property x of the {n: 1} object, assigns {n: 2} to foo, and assigns the new value of foo{n: 2} – to the property x of the {n: 1} object.

The important thing is that the foo that foo.x refers to is determined before foo changes.

See section 11.13.1 of the ES5 spec:

> 1. Let lref be the result of evaluating LeftHandSideExpression. > > 2. Let rref be the result of evaluating AssignmentExpression.

The assignment operator associates right to left, so you get:

foo.x = (foo = {n: 2})

The left hand side is evaluated before the right hand side.

Solution 2 - Javascript

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

Here foo refers to {n:1} object before assignment i.e. before the statement is executed.

The statement can be re-written as foo.x = (foo = {n:2});

In object terms the above statement can be re-written as {n:1}.x = ( {n:1} = {n:2} );

Since assignment happens from right to left only. So here we just have to keep a check that foo is referring to which object before execution starts.

On solving the R.H.S: foo = {n:2}; Now foo is referring to {n:2};

Coming back on the problem we are left with:

foo.x = foo;

Now foo.x on L.H.S is still {n:1}.x whereas foo on R.H.S is {n:2}.

So after this statement gets executed {n:1} will become { n:1, x:{n:2} } with bar still referring to it. Where as foo will now be referring to {n:2}.

So on execution foo.x gives undefined as there is only 1 value in foo which is {n:2}.

But if you will try executing bar.x it will give {n:2}. Or if you will just execute bar the result will be

Object {n: 1, x: Object}

Solution 3 - Javascript

As I understand expression :

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

just exactly the same as:

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

And after this it's became obvious that:

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

Solution 4 - Javascript

I thought I'd add another, what I found to be, helpful way of thinking about this.

Those last variable assignments are equivalent to writing bar.x = foo = {n:2};, because those variables are just references to the same thing in memory.

In other words, foo and bar are, at first, both referencing the same object, {n:1}. When you use foo.x =, you are accessing {n:1} and adding the x property to it. This could be done with either bar or foo because they both point to that same object in memory! It makes no difference.

Then when you complete that line, foo.x = foo = {n:2}, you are creating another, brand new, object in memory via object literal syntax and setting foo to point to that object, {n:2}, instead of what is now {n:1, x: {n: 2}. This doesn't affect what foo pointed to when you added the x property to it, though.

This is pretty confusing, but I think makes sense you think about the fact that variables are just pointers to places/objects in memory, and that object literal syntax isn't changing the previously existing object (even though they look similar). It's creating a brand new one.

The beginning of accepted answer to this question may be helpful as well.

Solution 5 - Javascript

It is a matter of understanding that object variables are merely references to the objects in JavaScript and not objects themselves.

var foo = {n: 1} -> foo refers to the real object {n: 1} var bar = foo -> bar is now also a reference to the real object {n: 1}

The tricky part is of course the 3rd line: foo.x = foo = {n: 2}

This is equivalent to: (reference to {n: 1}).x = (foo = {n: 2}) -> after this line is completely evaluated, foo becomes a reference to the new object {n: 2}; however, since foo refers to the original object {n: 1} prior to the evaluation of the line, the original object {n: 1} becomes {n: 1, x: [reference to]{n: 2}} after the line is evaluated, and the modified object will be accessible through the reference bar. If there was no reference bar, the original object would be destroyed

Solution 6 - Javascript

i think in Javascript you cant assign a value to a property which doesn't exist if the object isn't empty. so in this case foo object has a property and value pair which is {n:1} so since it isn't empty and it doesn't have a x property ,you cant assign but since you assign bar object a value which is foo object ,it will have the value whatever the foo is

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndyHuView Question on Stackoverflow
Solution 1 - JavascriptRy-View Answer on Stackoverflow
Solution 2 - JavascriptShardul Singh RanaView Answer on Stackoverflow
Solution 3 - JavascriptRon LavitView Answer on Stackoverflow
Solution 4 - JavascriptZach NagataniView Answer on Stackoverflow
Solution 5 - JavascriptHouView Answer on Stackoverflow
Solution 6 - JavascriptSenay YakutView Answer on Stackoverflow