Testet eine Javascript-if-Anweisung mit mehreren Bedingungen alle?

100

Wenn Sie in Javascript eine if-Anweisung mit mehreren zu testenden Bedingungen verwenden, werden diese von Javascript unabhängig davon getestet, oder wird sie vor dem Testen aller ausgeführt, wenn sie bereits falsch sind?

Beispielsweise:

 a = 1
 b = 2
 c = 1

 if (a==1 && b==1 && c==1)

Wird Javascript alle drei dieser Bedingungen testen oder, nachdem festgestellt wurde, dass b nicht gleich 1 ist und daher falsch ist, die Anweisung verlassen?

Ich frage aus Sicht der Leistung. Wenn ich zum Beispiel 3 komplexe jQuery-Selektoren teste, möchte ich, dass jQuery das DOM nicht dreimal durchläuft, wenn über das erste offensichtlich ist, dass es FALSE zurückgibt. (In diesem Fall wäre es sinnvoller, 3 if-Anweisungen zu verschachteln).

ADDENDUM: Eher eine Neugier, was ist der richtige Begriff dafür? Ich stelle fest, dass viele von Ihnen den Begriff "Kurzschluss" verwenden. Tun dies auch einige Sprachen und andere nicht?

DA.
quelle
@ Josh: Ich schätze die Idee, dass dies eine Mikrooptimierung ist, voll und ganz. Welches ist gut zu wissen. Das heißt, wenn eine Option optimierter ist als eine andere, ist es meiner Meinung nach gut, diese Methode zu kennen und sich daran zu gewöhnen. (Außerdem war ich auch sehr neugierig auf die Antwort)
DA.
21
Genau genommen ist dies keine vorzeitige Optimierung. In Sprachen mit Kurzschlusslogik ist es wichtig zu wissen, unter welchen Bedingungen einige Methoden nicht ausgeführt werden. wenn Sie sich zum Beispiel auf ihre Nebenwirkungen verlassen.
Rob
5
Hier ist eine weitere Frage zur "Kurzschlussbewertung": stackoverflow.com/questions/1232603/…
David
@David. Vielen Dank! Interessante Lektüre.
DA.

Antworten:

151

Der &&Bediener "schließt kurz" - das heißt, wenn die linke Bedingung falsch ist, macht er sich nicht die Mühe, die rechte zu bewerten.

Ebenso schließt der ||Bediener kurz, wenn die linke Bedingung erfüllt ist.

BEARBEITEN: Sie sollten sich jedoch keine Sorgen um die Leistung machen, bis Sie ein Benchmarking durchgeführt und festgestellt haben, dass es sich um ein Problem handelt. Vorzeitige Mikrooptimierung ist der Fluch der Wartbarkeit.

Anon.
quelle
1
Hervorragende Antwort (sowohl der technische Teil als auch das Managementproblem). Vielen Dank!
DA.
5
Wenn Sie jemals möchten, dass alle Teile der booleschen Anweisung ausgeführt werden, können Sie & und | verwenden für und und oder nachträglich
Zoidberg
25
Bei dieser Bedingung geht es nicht unbedingt immer um Leistung. Manchmal führen Sie eine Nullprüfung durch und sagen, wenn Ihre Nullprüfung Bedingung a ist. Wenn Sie dann versuchen, a (b == Wert + 1) für Ihre zweite Prüfung durchzuführen, erhalten Sie eine Fehlermeldung, wenn alle drei Bedingungen erfüllt sind.
Infocyde
4
In der Tat geht es beim Kurzschließen nicht um Leistung. Die ursprüngliche Frage wurde jedoch unter dem Gesichtspunkt der Leistung gestellt.
Anon.
1
sehr gut. Diese Art der Mikrooptimierung kann (unter anderem) einen großen Einfluss auf eine Scroll-Ereignisschleife haben, beispielsweise für die Parallaxenberechnung mehrerer Elemente oder sogar für einen klebrigen Balken. Nehmen Sie dieses Beispiel: if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)Die zweite Bedingung ist eine teurere Berechnung, die erste ist nur ein Boolescher Wert. :)
Antoni
13

Unter Leistungsgesichtspunkten ist dies keine Mikrooptimierung.

Wenn wir 3 Boolesche Variablen haben, a, b, c, ist das eine Mikrooptimierung.

Wenn wir 3 Funktionen aufrufen, die boolesche Variablen zurückgeben, kann jede Funktion lange dauern, und es ist nicht nur wichtig, diese Kurzschlüsse zu kennen, sondern auch in welcher Reihenfolge. Beispielsweise:

if (takesSeconds() && takesMinutes())

ist viel besser als

if (takesMinutes() && takesSeconds())

wenn beide gleich wahrscheinlich false zurückgeben.

Brad
quelle
12

Deshalb können Sie in Javascript Code wie tun

var x = x || 2;

Was bedeuten würde, dass wenn x undefiniert oder anderweitig 'falsch' ist, der Standardwert 2 ist.

Azazul
quelle
3
Dies könnte auch dann funktionieren, wenn JS die Kurzschlussauswertung nicht unterstützt.
Pswg
1
Ist das das Äquivalent eines ternären?
Mark Carpenter Jr
10

Falls sich jemand fragt, ob es eine Möglichkeit gibt, die Auswertung aller Zustände zu erzwingen , können in einigen Fällen die bitweisen Operatoren &und |verwendet werden

var testOr = true | alert(""); //alert pops up
var testAnd = false & alert(""); //alert pops up

Diese sollten sehr vorsichtig verwendet werden, da bitweise Operatoren arithmetische Operatoren sind, die mit einzelnen Bits ihres Operanden arbeiten und nicht immer als "Nicht-Kurzschluss" -Version von &&und fungieren können||

Beispiel:

-2147483648 && 1 = 1 

aber

-2147483648 & 1 = 0

Hoffe, es hilft jemandem, der hier angekommen ist und nach solchen Informationen sucht (wie ich) und danke an @Max für die Korrektur und das Gegenbeispiel

ivcandela
quelle
1
Diese Antwort ist falsch. & und | sind bitweise Operatoren, sie sind KEINE 'Nicht-Kurzschlussversionen von && und ||'. Bitweise Operatoren sind arithmetische Operatoren, die mit einzelnen Bits ihres Operanden arbeiten. Beispiel: -2147483648 && 1 = 1 aber -2147483648 & 1 = 0. Weitere Informationen hier: en.wikipedia.org/wiki/Bitwise_operation
Max
1
@Max eigentlich wusste ich das nicht, ich benutze das (was ich jetzt "Trick" nenne), seit ich C studiert habe. Glücklicherweise sind solche Eingaben, die meinen Code gebrochen hätten, nie aufgetaucht. Ich habe meine Antwort korrigiert, ich schulde dir
ivcandela
@ DJDaveMark Entschuldigung, ich konnte Ihre false && (alert(""))Lösung nicht zum
Laufen bringen
@ivcandela Weder könnte ich. Wenn ich nicht auf meinem Handy wäre, hätte ich es getestet 1.; o) Schade, dass Sie keine Kommentare bearbeiten können. Ich habe es gerade gelöscht und unten ein weiteres hinzugefügt
DJDaveMark
Der einfachere und bessere Weg, die Auswertung zu erzwingen, besteht darin, die Ergebnisse in Variablen zu speichern und dann gegen die Variablen zu testen, dh:var a=false; var b=check(); alert(a && b);
DJDaveMark
7

Es werden nur alle Bedingungen getestet, wenn die ersten zutreffen. Testen Sie es selbst:

javascript: alert (false && alert("A") && false);
Albertein
quelle
3

Es schließt kurz - nur a und b werden in Ihrem Beispiel verglichen.

David M.
quelle
3

Ein weiterer Grund, warum die Auswertung mit einem oder mehreren Parametern links gestoppt wird.

if (response.authResponse && (response.authResponse.accessToken! = user.accessToken)) {...}

Die zweite Auswertung setzt voraus, dass die erste wahr ist, und gibt keinen Kompilierungsfehler aus, wenn response.authResponse null oder undefiniert usw. ist, da die erste Bedingung fehlgeschlagen ist.

Andere Sprachen hatten dieses Problem in den frühen Tagen und ich denke, es ist jetzt ein Standardansatz beim Erstellen von Compilern.

PazoozaTest Pazman
quelle
2

Es wird beendet, nachdem festgestellt wurde, dass b nicht gleich eins ist.

Annie
quelle
2

Für alle, die mit dieser Frage verwirrt sind, weil sie das Kurzschlussverhalten bei Verwendung eines ||in Verbindung mit einem ?Operator wie diesem nicht sehen:

x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected

Es scheint, dass die Kurzschlussregel nicht funktioniert. Warum bewertet es den zweiten Term des ||(wahr? 2: 3), wenn der erste wahr ist? Es stellt sich heraus, dass es sich um ein Problem mit der Reihenfolge der Operationen handelt, da das oben Genannte dem entspricht

x = (1 || true) ? 2 : 3

mit dem ||zuerst ausgewerteten und dem ?ausgewerteten zweiten. Was Sie wahrscheinlich wollen, ist:

x = 1 || (true ? 2 : 3)

BrightEyed
quelle