51

Am not new to JS or its syntax, but sometimes, the semantics of the language has me stumped at times. At work today, a colleague mentioned this:

var a = b = [];

is not the same as

var a = [], b = [];

or

var a = []; var b = [];

since the first version actually assigns the reference to an empty array to a and b. I couldn't quite accept this as true, but I'm not sure. What do you all think?

Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
JamieJag
  • 1,541
  • 2
  • 11
  • 18
  • 5
    See http://stackoverflow.com/questions/1758576/multiple-left-hand-assignment-with-javascript/1758912#1758912 – Crescent Fresh Aug 02 '10 at 11:41
  • Thank you, Crescent Fresh - I didn't quite see that question because I was looking for "chained assignment". – JamieJag Aug 04 '10 at 13:12
  • Does this answer your question? [Multiple left-hand assignment with JavaScript](https://stackoverflow.com/questions/1758576/multiple-left-hand-assignment-with-javascript) – ggorlen Jun 03 '21 at 05:31

7 Answers7

58

Yes, they're not the same. var a = b = [] is equivalent to

var a;
b = [];
a = b;

Not only do both a and b get assigned the same value (a reference to the same empty array), b is not declared at all. In strict mode in ECMAScript 5 and later, this will throw a ReferenceError; otherwise, unless there is already a variable b in scope, b is silently created as a property of the global object and acts similarly to a global variable, wherever the code is, even inside a function. Which is not good.

You can see this quite easily:

(function() {
    var a = b = [];
})();

console.log(b); // Shows []
Tim Down
  • 318,141
  • 75
  • 454
  • 536
12

Your colleague is right:

var a = b = [];
a.push('something');
console.log(b); // outputs ["something"]

but:

var a = [],
  b = [];
a.push('something');
console.log(b); // outputs []
DecPK
  • 24,537
  • 6
  • 26
  • 42
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
3

Your colleague is right. The first statement creates a new, empty array. Then, a reference to this array is assigned to b. Then, the same reference (which is the result of the assignment expression) is assigned to a. So a and b refer to the same array.

In all other cases, you create two individual arrays.

By the way: This behavior is quite common and is the same in all C based programming languages. So this is not JavaScript specific.

h2stein
  • 546
  • 3
  • 13
  • Thanks for your reply, Tobias, and also for pointing out the commonality in all C-based languages. – JamieJag Aug 04 '10 at 09:55
  • This can be tested with arrays in JS: `["dog"] === ["dog"];` returns false, but `var a = b = ["dog"]; a === b;` returns true. – b00t Jun 14 '16 at 22:01
3

With the first example b is a reference to a, and b becomes a global variable, accessible from anywhere (and it replaces any b variable that may already exist in the global scope).

Fabien Ménager
  • 140,109
  • 3
  • 41
  • 60
3

To complement the already provided answers. ref assignments are different from value assignments

var x = y = 3; // by value
y++; // 4
x; // 3

var a = b = []; // by ref
b.push(1); // [1];
a; // [1]
a = [];
a.push(2); // [2];
b; // [1]

Now that we've addressed 2 two, your question also makes reference to linting, which is the practice of "pretty code" (not functional). In fact, JSHint has deprecated all their "pretty code rules"

That been said, I usually use the following style.-

var a, b, c, // first row all unassigned
    x = 1, // 1 row per assigned
    y = 2,
    list = [
       'additional',
       'indentation'
    ],
    obj = {
       A: 'A',
       B: 'B'
    };
var z = y +2; // created a new `var` cluster since it uses a var from the previous
percebus
  • 799
  • 1
  • 8
  • 21
1

To accomplish this, you need to split the var declaration from the chained assignment (see: http://davidshariff.com/blog/chaining-variable-assignments-in-javascript-words-of-caution/ ).

E.g.

var one = 1, two = 2;

one = two = 3; /* Now both equal 3 */

But if you do as you described (var one = two = 3; in this example) two leaks into the global space, while one is declared in the local scope.

Campbeln
  • 2,880
  • 3
  • 33
  • 33
0

Since your question is if it's ok or not, it's ok except in strict mode. Modules are in strict mode by default, so it's not allowed.

<script>
  const a=b=1 // allowed
<script>
<script>
  "user strict"
  const a=b=1 // error
<script>
<script type="module">
  const a=b=1 // error
<script>
Jonathan
  • 1,007
  • 16
  • 12