Кілька лівих завдань з JavaScript


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

Це еквівалентно цьому:

var var1 = var2 = var3 = 1;

Я впевнений, що це порядок визначення змінних: var3, var2, var1, який був би еквівалентний цьому:

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

Чи є спосіб підтвердити це в JavaScript? Можливо, використовуєте якийсь профілер?


6
НАЗНАЧЕННЯ ПРАВИЛЬНО
НАЛИВО

це також застосовується, якщо я використовую this.var1 = this.var2 = this.var3 = 1?
Gangadhar JANNU

Відповіді:


404

Насправді,

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));

44
Данг, це несподівано. Дякую за пораду, я буду стежити за цим.
Девід Калхун

10
@ SkinnyG33k, тому що справа зліва. тож він розбере найбільше правий перед самим лівим. так var var1=var2буває після var3 = 1і після var2 = var3. це якvar3=1; var2=var3; var var1=var2
gcb

12
Просто зауважте: якщо ви знаєте, що хочете зробити подібні речі достроково, ви все одно можете розділити це визначення із завдання. Отже: var v1, v2, v3;Потім згодом: v1 = v2 = v3 = 6;вони все ще будуть в локальному масштабі. Оскільки Давид згадав про сповіщення, це діятиме так, як і очікувалося (якщо було попередньо):alert(v1 = v2 = v3 = 6);
ShawnFumo

3
Саме так. Але якщо ми будемо слідувати деяким загальним найкращим практикам, то в цьому випадку, оголошуючи наші змінні вгорі, ми можемо уберегтися від небажаних помилок та уникнути проникнення локальних змінних у глобальну область. Дивіться: jsfiddle.net/gleezer/r9Mu8/1
Nobita

1
"Данг, це несподівано". Чому це було б несподівано? Більшість мов вимагає оголосити свої змінні перед використанням. JavaScript не відрізняється, якщо ви знехтуєте оголошувати свою змінну, вона за замовчуванням відповідає глобальному об'єкту вікна. Почніть використовувати «використовувати строгий» у своєму JavaScript, і ви станете кращим програмістом JavaScript.
Камберлен

20

Призначення в javascript працює справа наліво. var var1 = var2 = var3 = 1;.

Якщо значення будь-якої з цих змінних знаходиться 1після цього твердження, то логічно воно повинно починатися справа, інакше значення або var1і var2було б невизначене.

Ви можете вважати це рівнозначним тому, var var1 = (var2 = (var3 = 1));де вперше оцінюється внутрішній набір дужок.


1
Дякую, це безумовно допомагає. Це допомагає думати з точки зору того, які помилки будуть кинуті, якби їх оцінювали, окрім справа наліво (у цьому випадку помилка полягала б у тому, що var1 / var2 не визначено).
Девід Калхун

5
Це насправді помилка синтаксису. Не можна (відразу після var. Видалення зовнішнього набору дужок дозволяє компілювати без помилок, var var1 = (var2 = (var3 = 1));. У той час я відчував, що це не так ілюструє суть, але я вважаю, що це те саме.
Джастін Джонсон

var var1 = var2 = var3 = 1;. дорівнює var var3 = 1; var var2 = var3; var var1 = var2;
xgqfrms

8

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; 

8
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

4

Спробуйте це:

var var1=42;
var var2;

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

Зверніть увагу на сингл '=' у першому сповіщенні. Це покаже, що результатом виразу присвоєння є присвоєне значення, а друге попередження покаже вам, що присвоєння відбулося.

З цього випливає логічно, що завдання повинні бути прикуті справа наліво. Однак, оскільки це все атомно для javascript (там немає різьблення), певний двигун може вибрати оптимізувати його дещо інакше.


1
Дякую за відповідь. Я думаю, що я шукав спосіб використовувати сповіщення, зберігаючи структуру множинного призначення (a = b = c), але я не думаю, що це можливо.
Девід Калхун

1
Окремі висловлювання, подібні до javascript (і, хоча декілька виразів, що все працює в одному висловлюванні), можна вважати атомними. Вам доведеться розбити це.
Джоел Куехорн

1

На сьогодні ясно, що вони не однакові. Спосіб кодування, який є

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

А як щодо дозволу на призначення? Точно так само, як і var, не дозволяйте дозволу заплутати вас через область блоку.

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

Ми могли б зробити наступне:

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

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


-3

coffee-script може досягти цього за допомогою апломба ..

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

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


7
Це насправді не відповідає на питання. Будь ласка, перечитайте питання.
Мартін

30
кого піклується про coffeescript
неаумузичний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.