Hat JavaScript eine Kurzschlussauswertung?


101

Ich würde gerne wissen, ob JavaScript eine "Kurzschluss" -Bewertung wie && Operator in C # hat. Wenn nicht, würde ich gerne wissen, ob es eine Problemumgehung gibt, deren Übernahme sinnvoll ist.


2
Bitte. Ich habe https://www.google.com/search?q=site:stackoverflow.com+%sals Suchverknüpfung (Chrome / Firefox) hinzugefügt, um die Suche zu beschleunigen.
Rob W


Antworten:


117

Ja, JavaScript hat eine "Kurzschluss" -Auswertung.

if (true == true || foo.foo){
    // Passes, no errors because foo isn't defined.
}

Live DEMO

if (false && foo.foo){
    // Passes, no errors because foo isn't defined.
}

Live DEMO


8
So kurzgeschlossen ist es der Standard in JS?
GibboK

1
Danke gdoron, bitte hilf mir zu verstehen ... in C # habe ich auch einen binären Operator wie & also müssen beide Operanden wahr sein, um zu übergeben, stattdessen mit && in C
GibboK

1
@ GibboK. Dann kann es natürlich keinen Short-circuitmit diesem Logikoperator geben. Probieren Sie es einfach selbst aus. Nutze meine Demo.
Gdoron unterstützt Monica

2
@ GibboK: Überprüfen Sie diese Bedienerreferenz . Und ja, es gibt auch einen binären UND-Operator in JS.
Bergi

5
@ GibboK. JA im Standard! Aber ein guter Kommentar, wie in Zeiten der JIT-Kompilierungsmagie in Javascript-Implementierungen, möchte man wirklich wissen, ob etwas "der Standard" ist oder möglicherweise der Implementierung unterliegt. Die Art und Weise, wie eine Bedingungsanweisung mit binären logischen Operatoren bewertet wird und (Kurzschluss) ein Standardverhalten ist ecma-international.org/ecma-262/5.1/#sec-11.11
humanityANDpeace

21

Diese Antwort geht sehr detailliert darauf ein, wie funktioniert in JavaScript mit allen Gotchas und auch relevanten Themen wie der Priorität von Operatoren. Wenn Sie nach einer schnellen Definition suchen und bereits verstehen, wie Kurzschlüsse funktionieren, würde ich empfehlen, andere Antworten zu überprüfen.


Was wir (dachten wir) bisher wussten:

Lassen Sie uns zunächst das Verhalten untersuchen, mit dem wir alle vertraut sind, und zwar innerhalb des if()Blocks, in dem wir &&überprüfen, ob die beiden Dinge sind true:

if (true && true) {
   console.log('bar');
} 

Ihr erster Instinkt ist wahrscheinlich zu sagen: "Ah ja, ganz einfach, der Code führt die Anweisung aus, wenn beide expr1und expr2als ausgewertet werden. true"

Ja und nein. Sie sind technisch korrekt, das ist das Verhalten, das Sie beschrieben haben, aber genau so wird der Code nicht bewertet, und wir müssen tiefer gehen, um ihn vollständig zu verstehen.


Wie genau ist das &&und ||interpretiert?:

Es ist Zeit, "unter die Haube der Motor ". Betrachten wir dieses praktische Beispiel:

function sanitise(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

let userinput = 0xFF; // as an example
const res = sanitise(userinput) && userinput + 5

console.log(res);

Nun, das Ergebnis ist 260... aber warum? Um die Antwort zu erhalten, müssen wir verstehen, wie die Kurzschlussbewertung funktioniert.

Durch die MDN-Definition wird der &&Operator in wie expr1 && expr2folgt ausgeführt:

Wenn expr1konvertiert werden kann, truewird zurückgegeben expr2; sonst kehrt zurück expr1.

Das bedeutet, dass in unserem praktischen Beispiel const resdas folgendermaßen bewertet wird:

  1. Aufrufen expr1-sanitise(0xFF)
  2. 0xFF ist eine gültige Hexadezimalzahl für 250, sonst würde ich zurückkehren NaN
  3. Das expr1gab einen "wahrheitsgemäßen" Wert zurück, Zeit zum Ausführen expr2 (sonst würde ich aufhören, da NaNes falsch ist)
  4. Da userinputtruthy (eine Zahl) ist, kann ich hinzufügen , +5um es
  • "Wahrheit" bedeutet, dass der Ausdruck als wahr bewertet werden kann. Hier ist eine Liste von wahrheitsgemäßen und falschen Ausdrücken.

So konnten wir mit einer einfachen Bedienung des Operators zusätzliche ifBlöcke und weitere isNaNÜberprüfungen vermeiden &&.


Wie es wirklich funktioniert:

Inzwischen sollten wir zumindest ein Bild davon haben, wie die Bediener arbeiten. Die universelle Regel lautet:

  • (some falsy expression) && expr wird zu falschem Ausdruck ausgewertet
  • (some truthy expression) || expr wird zum wahrheitsgemäßen Ausdruck auswerten

Hier einige weitere Beispiele zum besseren Verständnis:

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() && b() ){
     console.log('foobar'); 
}

//Evaluates a() as false, stops execution.

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() || b() ){
     console.log('foobar'); 
}

/* 1. Evaluates a() as false
   2. So it should execute expr2, which is `b()`
   3. b() returned as true, executing statement `console.log('foobar');`
*/


Eine letzte lästige, aber sehr wichtige Sache [Operator Precedence]:

Schön, hoffentlich kriegst du den Dreh raus! Das Letzte, was wir wissen müssen, ist eine Regel über die Priorität von Operatoren, das heißt:

  • Der &&Operator wird immer vor dem ||Operator ausgeführt.

Betrachten Sie das folgende Beispiel:

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log(a() || b() && c());

// returns a() and stops execution

Dies wird als, vielleicht verwirrend für einige als zurückkehren a(). Die Vernunft ist ganz einfach, es ist nur unser Sehvermögen, das uns täuscht, weil wir es gewohnt sind, von links nach rechts zu lesen. Nehmen wir das console.log()und was nicht raus und konzentrieren uns nur auf die Bewertung

true || false && false

Nun, um Ihren Kopf darum zu wickeln:

  1. Wir sagten, der &&Operator hat Vorrang, daher wird er als erster bewertet. Denken Sie an die Definition, damit wir uns die Bewertung besser vorstellen können

    expr1 && expr2

    Wo:

    • expr2 ist false
    • expr1 ist true || false
  2. Das war also der schwierige Teil, jetzt true || falsewird ausgewertet (die expr1- linke Seite von &&).

    • Wenn der ||Operator die Ausführung stoppt, wenn expr1 || expr2in expr1als wahr bewertet wird, expr1wird die Ausführung ausgeführt und die Codeausführung wird gestoppt .
  3. Der zurückgegebene Wert ist true

Nun ... das war ziemlich knifflig, alles wegen der wenigen seltsamen Regeln und Semantik. Aber denken Sie daran, Sie können sich immer der Vorrangstellung des Operators entziehen ()- genau wie in der Mathematik

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log((a() || b()) && c());

/* 1. The () escape && operator precedence
   2. a() is evaluated as false, so expr2 (c()) to be executed
   3. c()  
*/


Ich würde 1) das Wort "Compiler" nicht verwenden. "Motor" ist genauer. 2) Nicht über expr1und expr2 oder condition1oder was auch immer reden , das ist nur verwirrend. Entscheiden Sie sich für eine, Sie können auch lokale Variablen einführen, z. const expr1 = true; if(expr1 && ...)
Jonas Wilms

@ JonasWilms danke für die Eingabe, hat die Antwort entsprechend geändert.
Samuel Hulla

1
Dies beantwortet die gestellte Frage immer noch nicht direkt.
Kevin B

7
Dies ist die beste "großartige Antwort, die die Frage nicht explizit beantwortet" , die ich je gesehen habe ...
Gerardo Furtado

1
Dies ist die richtige Antwort mit einer tiefen Erklärung, sollte als akzeptiert und viel mehr positiv bewertet werden als derzeit!
Alexander Kim
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.