In JavaScript, is chained assignment okay?
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?
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 []
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 []
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.
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).
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
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.
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>
精彩评论