10

In this post, Multiple left-hand assignment with JavaScript, @Crescent Fresh says JavsScript left-hand assignment is right associative. But the following code seems to me it breaks right associativeness:

var a = {n: 1};
a.x = a = {n: 2};
console.log(a.x);// undefined

Can anyone explain why a.x is undefined?

Edit:The snippet above is to test "right associativeness", in real world please do not write similar code.

Community
  • 1
  • 1
尤慕李
  • 425
  • 6
  • 15

3 Answers3

7

It is right associative. It's simply that the identifier a is bound to a reference before the statement executes.

We can witness this with the following:

var a, b;
a = b = { n: 1 };
a.x = a = {n: 2};  // a.x refers to the x property of the value a references
                   //     before this statement executes
console.log(a);    // {n: 2}
console.log(b);    // {n: 1, x: {n: 2}}

If = were left associative, b.x would be a circular reference back to b after the third line executes, but it isn't.


Can anyone explain why a.x is undefined?

Yes, this is what happens when the line a.x = a = {n: 2} executes:

  1. The value {n: 2} is assigned to the variable a
  2. The value {n: 2} is assigned to the x property of the object that a referred to before the statement started executing.

Nothing is assigned to the x property of a's new value. That's why a.x is undefined.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
6

tl;dr — JS works out where to put the value before working out what that value is, and a side effect of working out what that value is changes the value of a.


See the spec for simple assignment.

Step 1 is "Let lref be the result of evaluating LeftHandSideExpression."

Step 2 is "Let rref be the result of evaluating AssignmentExpression."

So the first thing that happens is that a property x is created on the object stored in a (where n is 1).

Then the right hand side is evaluated (which ends up overwriting a with a new object where n is 2).

Then the result of that expression (that object where n is 2) is assigned to x on the original object (where n is 1).

You can see this in effect with:

"use strict";
var a = {n: 1};
var b = a;

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

console.log(a);
console.log(b);
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Answers from @JLRishe and Quentin are both correct, but stackoverflow allows only one answer to be accepted:(. I have voted up both and accepted the latter because an answer with specifaction referencing is more solid and convincing. Thank you, sir. – 尤慕李 Dec 20 '15 at 00:57
  • For js **reference**, here is a great article [Why is (0,obj.prop)() not a method call](http://www.2ality.com/2015/12/references.html) from Dr. Axel Rauschmayer – 尤慕李 Dec 20 '15 at 00:59
0

in java script Objects are passed around by reference. They are never copied.

var a = {n:1}

so earlier a has reference of an object which has a property n=1

on second statement a.x = a = {n:2} a.x has added a property x on previous object whose value is an object with property n = 2 the same statement assign a the reference of new object.

Nitin9791
  • 1,124
  • 1
  • 14
  • 17