В JavaScript привязано к цепочке?
Я не новичок в JS или его синтаксисе, но иногда семантика языка иногда меня раздражает. На работе сегодня коллега упомянул об этом:
var a = b = [];
не совпадает с
var a = [], b = [];
или
var a = []; var b = [];
так как первая версия фактически присваивает ссылку на пустой массив на a и b. Я не мог признать это правдой, но я не уверен. Что вы все думаете?
Ответы
Ответ 1
Да, они не одинаковы. var a = b = []
эквивалентно
var a;
b = [];
a = b;
Мало того, что a
и b
получают одинаковое значение (ссылка на один и тот же пустой массив), b
вообще не объявляется. В строгом режиме в ECMAScript 5 и более поздних версиях это вызовет ReferenceError
; в противном случае, если в области видимости уже нет переменной b
, b
автоматически создается как свойство глобального объекта и действует аналогично глобальной переменной, где бы ни находился код, даже внутри функции. Что не хорошо.
Вы можете увидеть это довольно легко:
(function() {
var a = b = [];
})();
console.log(b); // Shows []
Ответ 2
Ваш коллега прав:
var a = b = [];
a.push('something');
console.log(b); // outputs ["something"]
а
var a = [], b = [];
a.push('something');
console.log(b); // outputs []
Ответ 3
Ваш коллега прав. Первый оператор создает новый пустой массив. Затем ссылку на этот массив присваивается b. Затем той же ссылке (которая является результатом выражения присваивания) присваивается значение a. Таким образом, a и b относятся к одному и тому же массиву.
Во всех остальных случаях вы создаете два отдельных массива.
Кстати: Такое поведение довольно распространено и одно и то же во всех языках программирования на языке C. Так что это не специфичный JavaScript.
Ответ 4
В первом примере b
есть ссылка на a
, а b
становится глобальной переменной, доступной из любого места (и она заменяет любую переменную b
, которая может уже существовать в глобальной области).
Ответ 5
Для этого вам нужно разбить объявление var
из привязанного назначения (см.
http://davidshariff.com/blog/chaining-variable-assignments-in-javascript-words-of-caution/).
например.
var one = 1, two = 2;
one = two = 3; /* Now both equal 3 */
Но если вы сделаете так, как вы описали (var one = two = 3;
в этом примере), two
просачивается в глобальное пространство, а one
объявляется в локальной области.
Ответ 6
В дополнение к уже предоставленным ответам. Присвоение ссылок отличается от присваивания значений
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]
Теперь, когда мы обратились к двум двум, ваш вопрос также касается линтинга, который является практикой "красивого кода" (не функционального). На самом деле, JSHint устарел во всех "правилах красивого кода"
Тем не менее, я обычно использую следующий стиль. -
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