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});
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};
?
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:
Let lref be the result of evaluating LeftHandSideExpression.
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.
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}
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