Wiele przypisań po lewej stronie za pomocą JavaScript


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

Jest to równoważne z tym:

var var1 = var2 = var3 = 1;

Jestem całkiem pewien, że jest to kolejność definiowania zmiennych: var3, var2, var1, co byłoby równoważne z tym:

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

Czy jest jakiś sposób na potwierdzenie tego w JavaScript? Używasz jakiegoś profilera?



czy to dotyczy również, jeśli używam this.var1 = this.var2 = this.var3 = 1?
Gangadhar JANNU

Odpowiedzi:


404

Tak właściwie,

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

nie jest równoważne z:

var var1 = var2 = var3 = 1;

Różnica polega na określaniu zakresu:

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!

W rzeczywistości pokazuje to, że przypisanie jest właściwe asocjacyjne. badPrzykład odpowiada:

var var1 = (window.var2 = (window.var3 = 1));

44
Dang, to nieoczekiwane. Dzięki za wskazówkę, będę na to uważał.
David Calhoun,

10
@ SkinnyG33k, ponieważ jest od prawej do lewej. więc najbardziej parsuje prawą, a najbardziej lewą. tak się var var1=var2dzieje po var3 = 1i po var2 = var3. to jakvar3=1; var2=var3; var var1=var2
gcb

12
Uwaga: jeśli wiesz, że chcesz to zrobić wcześniej, nadal możesz zerwać definicję z zadania. Więc: var v1, v2, v3;Potem: v1 = v2 = v3 = 6;będą nadal w zasięgu lokalnym. Odkąd David wspomniał o alertach, działałoby to zgodnie z oczekiwaniami (jeśli wstępnie zmieniono):alert(v1 = v2 = v3 = 6);
ShawnFumo 10.09.2013

3
Dokładnie. Ale jeśli zastosujemy się do kilku popularnych najlepszych praktyk, w tym przypadku deklarując nasze zmienne u góry, możemy uniknąć niepożądanych błędów i uniknąć wycieku zmiennych lokalnych do zasięgu globalnego. Zobacz: jsfiddle.net/gleezer/r9Mu8/1
Nobita

1
„Dang, to nieoczekiwane.” Dlaczego miałoby to być nieoczekiwane? Większość języków wymaga zadeklarowania zmiennych przed użyciem. JavaScript nie jest inny, jeśli zaniedbujesz deklarowanie zmiennej, domyślnie jest to obiekt globalnego okna. Zacznij używać „use strict” w swoim javascript, a staniesz się lepszym programistą JavaScript.
cchamberlain

19

Przypisanie w javascript działa od prawej do lewej. var var1 = var2 = var3 = 1;.

Jeśli wartość którejkolwiek z tych zmiennych jest następująca 1po tej instrukcji, logicznie rzecz biorąc, musiała zacząć od prawej strony, w przeciwnym razie wartość lub var1i var2byłaby niezdefiniowana.

Można go uznać za równoważny z var var1 = (var2 = (var3 = 1));miejscem, w którym najpierw oceniany jest wewnętrzny zestaw nawiasów.


1
Dzięki, to zdecydowanie pomaga. Pomaga zastanowić się, jakie błędy zostałyby zgłoszone, gdyby zostały ocenione inaczej niż od prawej do lewej (w tym przypadku błędem byłoby to, że var1 / var2 są niezdefiniowane).
David Calhoun,

5
To właściwie błąd składniowy. Nie możesz mieć (natychmiast po var. Usuwanie zewnętrzny zestaw nawiasie pozwala skompilować bez błędów var var1 = (var2 = (var3 = 1));. W tym czasie czułem, że nie ilustruje to zbyt dobrze, ale przypuszczam, że to samo.
Justin Johnson,

var var1 = var2 = var3 = 1;. równa się var var3 = 1; var var2 = var3; var var1 = var2;
xgqfrms

8

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

W tym przypadku varsłowo kluczowe dotyczy wszystkich trzech zmiennych.

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

co nie jest równoważne z tym:

var var1 = var2 = var3 = 1;

W tym przypadku varsłowo kluczowe za ekranami ma zastosowanie tylko w przypadku var1podnoszenia zmiennej, a reszta wyrażenia jest oceniana normalnie, więc zmienne var2, var3stają się globalne

JavaScript traktuje ten kod w następującej kolejności:

/*
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)jest logicznie (a ? b : a)i zachowuje się jak mnożenie (np. !!a * !!b)

(a || b)jest logiczne (a ? a : b)i zachowuje się jak dodawanie (np. !!a + !!b)

(a = 0, b)jest skrótem od nie dbania o ato, czy jest prawdą, domyślnie powróć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

Pierwszeństwo operatorów JavaScript (kolejność operacji)

Zauważ, że operator przecinka jest w rzeczywistości najmniej uprzywilejowanym operatorem, ale nawiasy są najbardziej uprzywilejowane i idą w parze podczas konstruowania wyrażeń jednowierszowych.


W końcu możesz potrzebować „thunks” zamiast wartości zapisanych na stałe, a dla mnie thunk jest zarówno funkcją, jak i wartością wynikową (ta sama „rzecz”).

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

windowInnerHeight(); // a thunk

4

Spróbuj tego:

var var1=42;
var var2;

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

Zwróć uwagę na pojedynczy „=” w pierwszym alercie. To pokaże, że wynikiem wyrażenia przypisania jest przypisana wartość, a 2. alert pokaże, że przypisanie nastąpiło.

Logicznie wynika, że ​​przypisanie musi być powiązane łańcuchem od prawej do lewej. Ponieważ jednak wszystko to jest atomowe w javascript (nie ma wątków), konkretny silnik może faktycznie zoptymalizować go nieco inaczej.


1
Dziękuję za odpowiedź. Wydaje mi się, że szukałem sposobu na użycie alertów przy jednoczesnym zachowaniu struktury wielokrotnego przypisania (a = b = c), ale nie sądzę, aby było to możliwe.
David Calhoun,

1
Indywidualne instrukcje takie jak javascript (i choć kilka wyrażeń, które wszystkie działają na jedną instrukcję) można uznać za atomowe. Trzeba by to zerwać.
Joel Coehoorn,

1

Jest już jasne, że nie są takie same. To znaczy sposób na kodowanie

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

A co powiesz na cesję? Dokładnie to samo, co var, nie pozwól, aby przypisanie let myliło cię z powodu zasięgu bloku.

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

Możemy wykonać następujące czynności:

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

Uwaga: btw, nie polecam używania wielu przypisań, nawet wielu deklaracji w tym samym wierszu.


-3

coffee-script można to osiągnąć za pomocą aplomb ..

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

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


7
To tak naprawdę nie odpowiada na pytanie. Przeczytaj ponownie pytanie.
Martin

30
kto dba o coffeescript
neaumusic 16.04.16
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.