Mehrfache Zuweisung für die linke Hand mit JavaScript

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

Dies entspricht:

var var1 = var2 = var3 = 1;

Ich bin mir ziemlich sicher, dass dies die Reihenfolge ist, in der die Variablen definiert sind: var3, var2, var1, was dem entspricht:

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

Gibt es eine Möglichkeit, dies in JavaScript zu bestätigen? Verwenden Sie möglicherweise einen Profiler?

David Calhoun
quelle
6
ÜBERTRAGUNG PASSIERT RECHTS, Javascript-Operator-Priorität zu verlassen
neaumusic
gilt das auch wenn ich benutze this.var1 = this.var2 = this.var3 = 1?
Gangadhar JANNU

Antworten:

404

Tatsächlich,

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

ist nicht gleichbedeutend mit:

var var1 = var2 = var3 = 1;

Der Unterschied liegt im Umfang:

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!

Tatsächlich zeigt dies, dass die Zuordnung richtig assoziativ ist. Das badBeispiel entspricht:

var var1 = (window.var2 = (window.var3 = 1));
Halbmond frisch
quelle
44
Dang, das ist unerwartet. Danke für den Tipp, darauf werde ich achten.
David Calhoun
10
@ SkinnyG33k weil es von rechts nach links ist. es wird also das am weitesten rechts stehende am weitesten links analysieren. so var var1=var2passiert nach var3 = 1und nach var2 = var3. Es ist wievar3=1; var2=var3; var var1=var2
GCB
12
Nur zur Anmerkung: Wenn Sie wissen, dass Sie so etwas im Voraus tun möchten, können Sie die Definition dennoch von der Zuweisung trennen. Also: var v1, v2, v3;Dann später: v1 = v2 = v3 = 6;Sie werden immer noch im lokalen Bereich sein. Da David Warnungen erwähnte, würde dies wie erwartet funktionieren (wenn vorab geändert):alert(v1 = v2 = v3 = 6);
ShawnFumo
3
Genau. Wenn wir jedoch einige gängige Best Practices befolgen, können wir in diesem Fall durch Deklarieren unserer Variablen oben unerwünschte Fehler vermeiden und verhindern, dass lokale Variablen in den globalen Bereich gelangen. Siehe: jsfiddle.net/gleezer/r9Mu8/1
Nobita
1
"Dang, das ist unerwartet." Warum sollte das unerwartet sein? In den meisten Sprachen müssen Sie Ihre Variablen vor der Verwendung deklarieren. JavaScript ist nicht anders. Wenn Sie es versäumen, Ihre Variable zu deklarieren, wird standardmäßig das globale Fensterobjekt verwendet. Beginnen Sie mit der Verwendung von 'use strict' in Ihrem Javascript und Sie werden ein besserer JavaScript-Programmierer.
Cchamberlain
19

Die Zuweisung in Javascript funktioniert von rechts nach links. var var1 = var2 = var3 = 1;.

Wenn der Wert einer dieser Variablen 1nach dieser Anweisung liegt, muss sie logischerweise von rechts begonnen haben, andernfalls wäre der Wert oder var1und var2undefiniert.

Sie können sich das als äquivalent dazu vorstellen, var var1 = (var2 = (var3 = 1));wo der innerste Satz von Klammern zuerst ausgewertet wird.

Justin Johnson
quelle
1
Danke, das hilft definitiv. Es ist hilfreich zu überlegen, welche Fehler ausgelöst würden, wenn sie nicht von rechts nach links ausgewertet würden (in diesem Fall wäre der Fehler, dass var1 / var2 undefiniert sind).
David Calhoun
5
Es ist eigentlich ein Syntaxfehler. Sie können nicht (sofort danach haben var. Durch Entfernen des äußeren Satzes von Klammern kann dieser fehlerfrei kompiliert werden var var1 = (var2 = (var3 = 1));. Zu der Zeit hatte ich das Gefühl, dass es den Punkt nicht ganz so gut illustrierte, aber ich nehme an, es ist das gleiche.
Justin Johnson
var var1 = var2 = var3 = 1;. gleich var var3 = 1; var var2 = var3; var var1 = var2;
xgqfrms
8

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

In diesem Fall gilt das varSchlüsselwort für alle drei Variablen.

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

was nicht gleichbedeutend ist mit:

var var1 = var2 = var3 = 1;

In diesem Fall hinter den Bildschirmen varSchlüsselwort nur anwendbar ist , var1um variable Hebe fällig und des Ausdrucks ruhen normalerweise ausgewertet wird , so dass die Variablen var2, var3immer Globals

Javascript behandelt diesen Code in dieser Reihenfolge:

/*
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; 
Gangadhar JANNU
quelle
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)ist logisch (a ? b : a)und verhält sich wie Multiplikation (zB !!a * !!b)

(a || b)ist logisch (a ? a : b)und verhält sich wie Addition (zB !!a + !!b)

(a = 0, b)ist kurz dafür, sich nicht adarum zu kümmern, ob es wahr ist, implizit zurückzukehrenb


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

Vorrang des JavaScript-Operators (Reihenfolge der Operationen)

Beachten Sie, dass der Kommaoperator tatsächlich der am wenigsten privilegierte Operator ist, Klammern jedoch die am meisten privilegierten und beim Erstellen einzeiliger Ausdrücke Hand in Hand gehen.


Möglicherweise benötigen Sie eher "Thunks" als fest codierte Werte, und für mich ist ein Thunk sowohl die Funktion als auch der resultierende Wert (dasselbe "Ding").

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

windowInnerHeight(); // a thunk
neaumusic
quelle
4

Versuche dies:

var var1=42;
var var2;

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

Beachten Sie das einzelne '=' in der ersten Warnung. Dies zeigt, dass das Ergebnis eines Zuweisungsausdrucks der zugewiesene Wert ist, und die zweite Warnung zeigt an, dass eine Zuweisung stattgefunden hat.

Daraus folgt logischerweise, dass die Zuordnung von rechts nach links verkettet sein muss. Da dies jedoch alles atomar für das Javascript ist (es gibt kein Threading), kann eine bestimmte Engine entscheiden, es tatsächlich ein wenig anders zu optimieren.

Joel Coehoorn
quelle
1
Danke für die Antwort. Ich glaube, ich habe nach einer Möglichkeit gesucht, die Warnungen zu verwenden, während die Mehrfachzuweisungsstruktur (a = b = c) beibehalten wurde, aber ich denke nicht, dass dies möglich ist.
David Calhoun
1
Einzelne Aussagen wie diese in Javascript (und, obwohl mehrere Ausdrücke, die alle zu einer einzigen Aussage führen) können als atomar betrachtet werden. Du müsstest es auflösen.
Joel Coehoorn
1

Inzwischen ist klar, dass sie nicht gleich sind. Der Weg zum Code ist

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

Und was ist mit der Zuweisung? Genau wie bei var, lassen Sie sich von der let-Zuweisung nicht aufgrund des Blockumfangs verwirren.

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

Wir könnten Folgendes tun:

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

Hinweis: Übrigens empfehle ich nicht, mehrere Zuweisungen zu verwenden, nicht einmal mehrere Deklarationen in derselben Zeile.

fenderOne
quelle
-3

coffee-script kann dies mit Gelassenheit erreichen ..

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

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

Alex Gray
quelle
7
Dies beantwortet die Frage nicht wirklich. Bitte lesen Sie die Frage erneut.
Martin
30
Wer kümmert sich um Coffeescript
Neaumusic