Многократное левостороннее назначение с JavaScript - PullRequest
171 голосов
/ 18 ноября 2009
var var1 = 1,
    var2 = 1,
    var3 = 1;

Это эквивалентно этому:

var var1 = var2 = var3 = 1;

Я вполне уверен, что это порядок, в котором определены переменные: var3, var2, var1, что эквивалентно этому:

var var3 = 1, var2 = var3, var1 = var2;

Есть ли способ подтвердить это в JavaScript? Возможно, вы используете какой-то профилировщик?

Ответы [ 7 ]

375 голосов
/ 18 ноября 2009

На самом деле,

var var1 = 1, var2 = 1, var3 = 1;

равно не эквивалентно:

var var1 = var2 = var3 = 1;

Разница в области видимости:

function good() {
  var var1 = 1, var2 = 1, var3 = 1;
}

function bad() {
  var var1 = var2 = var3 = 1;
}

good();
console.log(window.var2); // undefined

bad();
console.log(window.var2); // 1. Aggh!

На самом деле это показывает, что присвоение является ассоциативным. Пример bad эквивалентен:

var var1 = (window.var2 = (window.var3 = 1));
17 голосов
/ 18 ноября 2009

Назначение в JavaScript работает справа налево. var var1 = var2 = var3 = 1;.

Если значение какой-либо из этих переменных равно 1 после этого оператора, то логически оно должно начинаться справа, в противном случае значение или var1 и var2 будет неопределенным.

Вы можете думать об этом как об эквиваленте var var1 = (var2 = (var3 = 1));, где самый внутренний набор скобок вычисляется первым.

8 голосов
/ 30 апреля 2015
a = (b = 'string is truthy'); // b gets string; a gets b, which is a primitive (copy)
a = (b = { c: 'yes' }); // they point to the same object; a === b (not a copy)

(a && b) логически (a ? b : a) и ведет себя как умножение (например, !!a * !!b)

(a || b) логически (a ? a : b) и ведет себя как сложение (например, !!a + !!b)

(a = 0, b) - это сокращение, означающее, что все равно, если a верно, неявно возвращает b


a = (b = 0) && "nope, but a is 0 and b is 0"; // b is falsey + order of operations
a = (b = "b is this string") && "a gets this string"; // b is truthy + order of ops

Приоритет оператора JavaScript (порядок операций)

Обратите внимание, что оператор запятой на самом деле является оператором с наименьшими привилегиями, но круглые скобки являются наиболее привилегированными, и они идут рука об руку при построении однострочных выражений.


В конце концов вам могут понадобиться «thunks», а не жестко заданные значения, и для меня thunk - это и функция, и результирующее значение (одна и та же «вещь»).

const windowInnerHeight = () => 0.8 * window.innerHeight; // a thunk

windowInnerHeight(); // a thunk
7 голосов
/ 14 марта 2016

var var1 = 1, var2 = 1, var3 = 1;

В этом случае ключевое слово var применимо ко всем трем переменным.

var var1 = 1,
    var2 = 1,
    var3 = 1;

что не эквивалентно этому:

var var1 = var2 = var3 = 1;

В этом случае за экранами ключевое слово var применимо только к var1 из-за подъема переменной, а остальная часть выражения оценивается нормально, поэтому переменные var2, var3 становятся глобальными

Javascript обрабатывает этот код в следующем порядке:

/*
var 1 is local to the particular scope because of var keyword
var2 and var3 will become globals because they've used without var keyword
*/

var var1;   //only variable declarations will be hoisted.

var1= var2= var3 = 1; 
4 голосов
/ 18 ноября 2009

Попробуйте это:

var var1=42;
var var2;

alert(var2 = var1); //show result of assignment expression is assigned value
alert(var2); // show assignment did occur.

Обратите внимание на одиночное '=' в первом предупреждении. Это покажет, что результатом выражения присваивания является присвоенное значение, а во 2-м предупреждении будет показано, что присвоение произошло.

Логически следует, что назначение должно быть цепочкой справа налево. Однако, поскольку это все атомарно для javascript (нет потоков), конкретный движок может по-настоящему оптимизировать его немного по-другому.

0 голосов
/ 01 апреля 2019

Теперь ясно, что они не одинаковы. Способ кодирования, который

var var1, var2, var3
var1 = var2 = var3 = 1

А как насчет пусть присвоения? Точно так же, как var, не позволяйте заданию let сбить вас с толку из-за объема блока.

let var1 = var2 = 1 // here var2 belong to the global scope

Мы могли бы сделать следующее:

let v1, v2, v3
v1 = v2 = v3 = 2

Примечание: кстати, я не рекомендую использовать несколько назначений, даже не несколько объявлений в одной строке.

0 голосов
/ 15 октября 2015

coffee-script может сделать это с помощью aplomb ..

for x in [ 'a', 'b', 'c' ] then "#{x}" : true

[ { a: true }, { b: true }, { c: true } ]

...