Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a.x = a = {n: b} work in JavaScript?

Tags:

javascript

This is related to Javascript a=b=c statements.

I do understand that

foo = foo.x = {n: b}; // console.log(foo) => {n: b}

but

foo.x = foo = {n: b}; // console.log(foo) => {n: b}

It should equal to :

foo = {n: b};
foo.x = foo; // console.log(foo) => {n: b, x:object}

Am I missing something here?

like image 346
Seeliang Avatar asked Jun 24 '16 08:06

Seeliang


People also ask

What does => mean in JavaScript?

It's a new feature that introduced in ES6 and is called arrow function. The left part denotes the input of a function and the right part the output of that function.

What does the operator do in JavaScript?

What exactly is the JavaScript in operator? The JavaScript in operator is used to check if a specified property exists in an object or in its inherited properties (in other words, its prototype chain). The in operator returns true if the specified property exists.

What is &= in JS?

The bitwise AND assignment operator ( &= ) uses the binary representation of both operands, does a bitwise AND operation on them and assigns the result to the variable.

How many types of operators in JavaScript?

JavaScript Operators are as rich as what you'd expect from any modern language. There are four categories: arithmetic, comparison, assignment, and logical.


2 Answers

With:

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

The leading foo.x is partially evaluated first, enough to determine the exact target for the assignment, before proceeding to actually assign it.

It behaves more along the lines of:

var oldFoo = foo;
foo = {n: b};
oldFoo.x = foo;

This is mentioned in the standard. The left side of the = is evaluated (1.a) before the value is placed there (1.f):

AssignmentExpression : LeftHandSideExpression = AssignmentExpression

1) If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
a) Let lref be the result of evaluating LeftHandSideExpression.
...
f) Perform ? PutValue(lref, rval).

like image 77
Jonathan Lonowski Avatar answered Sep 27 '22 23:09

Jonathan Lonowski


This is because when you write

var foo = {};
foo.x = foo = {n: b} //a=b=c

while the line is being executed, foo is pointing to {} but when this statement is broken down to

foo.x = (foo = {n: b}) /a=(b=c)

foo's reference has changed from {} to {n:b} but foo in foo.x (a) is still pointing to old reference of foo since left hand expression was evaluated before assignment had begun.

As per the spec

  1. If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral,

    a. then Let lref be the result of evaluating LeftHandSideExpression.

Which means before the assignment foo.x was still having reference to old foo.

So, if you tweak your example a little bit by doing

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

In this example, you didn't change the reference to foo, only assigned new property, so the output now is

Object {z: 2, n: Object, x: Object}

Now, it has retained the reference to old foo since a new reference was not assigned hence all properties z, n and x are being retained.

like image 22
gurvinder372 Avatar answered Sep 28 '22 00:09

gurvinder372