Erklärung der Variablenzuweisung für JavaScript ODER (||)

351

Angesichts dieses Ausschnitts von JavaScript ...

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f = a || b || c || d || e;

alert(f); // 4

Kann mir bitte jemand erklären, wie diese Technik heißt (meine beste Vermutung steht im Titel dieser Frage!)? Und wie / warum funktioniert es genau?

Nach meinem Verständnis wird der Variablen fder nächste Wert (von links nach rechts) der ersten Variablen zugewiesen, deren Wert weder null noch undefiniert ist, aber ich habe nicht viel Referenzmaterial zu dieser Technik gefunden und habe Ich habe gesehen, dass es viel benutzt hat.

Ist diese Technik auch spezifisch für JavaScript? Ich weiß, dass etwas Ähnliches in PHP dazu führen würde, fdass ein echter boolescher Wert und nicht der Wert von sich dselbst vorliegt.

chattsm
quelle
4
Alte Frage, aber in Bezug auf PHP gibt es ein Konstrukt, das Sie verwenden können : $f=$a or $f=$b or $f=$c; // etc. PHP hat sowohl den ||Operator als auch den orOperator, die den gleichen Job machen. jedoch orausgewertet wird nach Zuordnung während ||vor ausgewertet wird. Dies gibt Ihnen auch den perlischen Stil von$a=getSomething() or die('oops');
Manngo
1
In PHP 5.3 können Sie den mittleren Teil des ternären Operators weglassen, um sich darauf zu stützen ... Sie können das auch etwas kürzer in so etwas schneiden: $f = $a ?: $b ?: $c;
Rei
1
Ab PHP 7 können Sie ??dies verwenden. $a = $b ?? 'default'
Spencer Ruskin
@SpencerRuskin $awird also der Wert von $bif $bis true zugewiesen , other 'default'?
Oldboy
Das stimmt. Schauen Sie sich den Null-Koaleszenz-Operator-Abschnitt auf dieser Seite an: php.net/manual/en/migration70.new-features.php
Spencer Ruskin

Antworten:

212

Erläuterungen finden Sie unter Kurzschlussauswertung . Es ist eine übliche Methode, diese Operatoren zu implementieren. Es ist nicht nur in JavaScript verfügbar.

entspannen
quelle
57
Denken Sie nur an die 'Gotcha', die besagt, dass die letzte immer zugewiesen wird, auch wenn sie alle undefiniert, null oder falsch sind. Das Festlegen von etwas, von dem Sie wissen, dass es am Ende der Kette nicht falsch, null oder undefiniert ist, ist ein guter Weg, um zu signalisieren, dass nichts gefunden wurde.
Erik Reppen
Ich habe diese Technik jahrelang gesehen, aber was mich gerade dann beeindruckt hat, als ich sie verwenden wollte, ist, dass das Ergebnis des Ausdrucks nicht in Boolesche Werte umgewandelt wird. Das kannst du später nicht mehr if( true == f ). Wenn eine Ganzzahl in f gespeichert wurde, gibt dieser Test immer false zurück.
9
Eigentlich kann man tun if(true == f), das ist das gleiche wie if(f): der Test passieren. Wenn Sie auch den Typ von testen möchten f, verwenden Sie einen strengen Vergleich : if(true === f), der in der Tat fehlschlägt.
Alsciende
5
Ja, Kurzschlussauswertung ist üblich. Der Unterschied liegt jedoch darin, wie JavaScript den letzten Wert zurückgibt, der die Ausführung angehalten hat. @ Anurags Antwort erklärt dies viel besser.
Ben.12
Ich bin mir nicht sicher, ob dies die beste Erklärung für Anfänger ist. Ich würde empfehlen: javascript.info/logical-operators
csguy
198

Dies wird vorgenommen, um einen Standardwert zuzuweisen , in diesem Fall den Wert von y, wenn die xVariable falsch ist .

Die booleschen Operatoren in JavaScript können einen Operanden zurückgeben und nicht immer ein boolesches Ergebnis wie in anderen Sprachen.

Der logische ODER-Operator (|| ) gibt den Wert seines zweiten Operanden zurück, wenn der erste falsch ist, andernfalls wird der Wert des ersten Operanden zurückgegeben.

Zum Beispiel:

"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"

Falsy Werte sind diejenigen , die coerce zu , falsewenn sie in Booleschen Kontext verwendet wird , und sie sind 0, null, undefined, eine leere Zeichenfolge, NaNund natürlich false.

CMS
quelle
1
+1 Gibt es so einen anderen Operator? Oder ist ||exklusiv.
OscarRyz
9
@Support (@Oscar): Der logische &&Operator hat ein ähnliches Verhalten. Er gibt den Wert des ersten Operanden zurück, wenn er an sich falsch ist, und gibt den Wert des zweiten Operanden zurück, nur wenn der erste wahr ist , z. B. ("foo" && "bar") == "bar"und(0 && "bar") == 0
CMS
12
Falsy ist in der Tat der Fachbegriff.
ChaosPandion
8
Also haben wir in diesem Beitrag etwas über ||, &&, "Falsy" und "Truly" gelernt. Beste Antwort mit "versteckten" Geschenken.
Alex
4
@ Alex NB: "Truthy" (! "Truly")
Bumpy
183

Javacript verwendet die Kurzschlussauswertung für logische Operatoren ||und &&. Es unterscheidet sich jedoch von anderen Sprachen darin, dass es das Ergebnis des letzten Werts zurückgibt, der die Ausführung angehalten hat, anstelle von a trueoder falsevalue.

Die folgenden Werte werden in JavaScript als falsch angesehen.

  • falsch
  • Null
  • "" (leerer String)
  • 0
  • Nan
  • nicht definiert

Die folgenden Beispiele ignorieren die Vorrangregeln des Operators und halten die Dinge einfach. Sie zeigen, welcher Wert die Auswertung angehalten hat und als Ergebnis zurückgegeben wird.

false || null || "" || 0 || NaN || "Hello" || undefined // "Hello"

Die ersten 5 Werte bis NaNsind falsch, daher werden sie alle von links nach rechts ausgewertet, bis sie den ersten Wahrheitswert erfüllen. Dies "Hello"macht den gesamten Ausdruck wahr, sodass alles weiter oben nicht ausgewertet wird und "Hello"als Ergebnis des Ausdrucks zurückgegeben wird . Ebenso in diesem Fall:

1 && [] && {} && true && "World" && null && 2010 // null

Die ersten 5 Werte sind alle wahr und werden ausgewertet, bis sie den ersten falschen Wert ( null) erfüllen , wodurch der Ausdruck falsch wird, also 2010nicht mehr ausgewertet wird und nullals Ergebnis des Ausdrucks zurückgegeben wird.

In dem von Ihnen angegebenen Beispiel wird diese Eigenschaft von JavaScript verwendet, um eine Zuweisung auszuführen. Es kann überall dort verwendet werden, wo Sie den ersten Wahrheits- oder Falschwert unter einer Reihe von Werten erhalten müssen. Dieser Code unten weist den Wert "Hello"zu, bda es einfacher ist, einen Standardwert zuzuweisen, als if-else-Prüfungen durchzuführen.

var a = false;
var b = a || "Hello";

Sie können das folgende Beispiel als Ausnutzung dieser Funktion bezeichnen, und ich glaube, es erschwert das Lesen von Code.

var messages = 0;
var newMessagesText = "You have " + messages + " messages.";
var noNewMessagesText = "Sorry, you have no new messages.";
alert((messages && newMessagesText) || noNewMessagesText);

Innerhalb der Warnung prüfen wir, ob sie messagesfalsch ist, und wenn ja, bewerten und zurückgeben noNewMessagesText, andernfalls bewerten und zurückgeben newMessagesText. Da es in diesem Beispiel falsch ist, halten wir bei noNewMessagesText an und alarmieren "Sorry, you have no new messages.".

Anurag
quelle
36
Dies ist meiner Meinung nach die beste Antwort aufgrund der folgenden Erklärung:However, it's different to other languages in that it returns the result of the last value that halted the execution, instead of a true, or false value.
Mastazi
1
@mastazi Ja, es sollte meiner Meinung nach fett gedruckt sein.
24.
6
Sollte die Antwort sein, zeigt es die Werte, die gegenüber Testfällen ausgewählt werden.
Dadan
Einverstanden, dies ist meine Lieblingsantwort, da sie speziell auf Bedenken hinsichtlich der Zuweisung von JavaScript-Variablen eingeht. Wenn Sie ein Ternär als eine der nachfolgenden Variablen zum Testen der Zuweisung (nach dem Operator) verwenden, müssen Sie das Ternär in Klammern setzen, damit die Zuweisungsbewertung ordnungsgemäß funktioniert.
Joey T
Dies sollte die akzeptierte Antwort sein
Alan
49

Javascript-Variablen werden nicht eingegeben, daher kann f ein ganzzahliger Wert zugewiesen werden, obwohl er über boolesche Operatoren zugewiesen wurde.

f wird der nächste Wert zugewiesen, der nicht gleich false ist . Also werden 0, false, null, undefined alle übergangen:

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'
Alsciende
quelle
13
Vergessen Sie ''in diesem Fall auch nicht gleich falsch.
Brigand
Upvote für den Hinweis auf das, f is assigned the NEAREST valuewas hier ein ziemlich wichtiger Punkt ist.
Steviejay
3
"Nearest" ist nicht ganz richtig, obwohl es so aussieht. Der boolesche ||Operator, der ein boolescher Operator ist, hat zwei Operanden: eine linke und eine rechte Seite. Wenn die linke Seite des ||ist truthy , wird die Operation Entschlüssen auf der linken Seite und der rechten Seite ignoriert. Wenn die linke Seite falsch ist , wird sie auf der rechten Seite aufgelöst. Also wird null || undefined || 4 || 0tatsächlich aufgelöst, zu undefined || 4 || 0welchem ​​aufgelöst wird, zu 4 || 0welchem ​​aufgelöst wird 4.
Devios1
29

Es gibt keine Magie. Boolesche Ausdrücke wie a || b || c || dwerden träge ausgewertet. Interpeter sucht nach dem Wert von a, es ist undefiniert, also ist es falsch, also geht es weiter, dann sieht es, bwas null ist, was immer noch ein falsches Ergebnis liefert, also geht es weiter, dann sieht es c- dieselbe Geschichte. Schließlich sieht dund sagt es "huh, es ist nicht null, also habe ich mein Ergebnis" und weist es der endgültigen Variablen zu.

Dieser Trick funktioniert in allen dynamischen Sprachen, in denen boolesche Ausdrücke verzögert kurzgeschlossen werden. In statischen Sprachen wird es nicht kompiliert (Typfehler). In Sprachen, die gerne boolesche Ausdrücke auswerten, wird ein logischer Wert zurückgegeben (dh in diesem Fall true).

Marcin
quelle
6
In der ziemlich statischen Sprache C # kann man das ?? Operator á la: Objekt f = a ?? b ?? c ?? d ?? e;
Herzmeister
2
herzmeister - danke! Ich wusste das nicht? Operator kann in C # verkettet und in faulen Bewertungstechniken verwendet werden
Marek
3
Wie an anderer Stelle erwähnt, wird dieser letzte dzugewiesen, unabhängig davon, ob er null / undefiniert war oder nicht.
BlackVegetable
Eine kleine Korrektur: Der ||Operator löst immer den gesamten Operanden auf der rechten Seite auf, wenn die linke Seite falsch ist. Als boolescher Operator werden nur zwei Eingaben angezeigt: die linke und die rechte Seite. Der Parser sieht sie nicht als eine Reihe von Begriffen, daher hört er nicht auf, wenn er den ersten Wahrheitswert findet, es sei denn, dieser Wert ist auch der linke Operand eines anderen ||.
devios1
8

Diese Frage hat bereits mehrere gute Antworten erhalten.

Zusammenfassend nutzt diese Technik eine Funktion zum Kompilieren der Sprache. Das heißt, JavaScript "schließt" die Auswertung von Booleschen Operatoren kurz und gibt den Wert zurück, der entweder dem ersten nicht falschen Variablenwert oder dem, was die letzte Variable enthält, zugeordnet ist. Siehe Anurags Erklärung der Werte, die als falsch ausgewertet werden.

Die Verwendung dieser Technik ist aus mehreren Gründen keine gute Praxis. jedoch.

  1. Lesbarkeit des Codes: Hierbei werden boolesche Operatoren verwendet. Wenn das Verhalten beim Kompilieren nicht verstanden wird, ist das erwartete Ergebnis ein boolescher Wert.
  2. Stabilität: Hierbei wird eine Funktion zum Kompilieren der Sprache verwendet, die über mehrere Sprachen hinweg inkonsistent ist. Aus diesem Grund kann diese Funktion möglicherweise in Zukunft geändert werden.
  3. Dokumentierte Funktionen: Es gibt eine Alternative, die diese Anforderungen erfüllt und in mehreren Sprachen konsistent ist. Dies wäre der ternäre Operator:

    ()? Wert 1: Wert 2.

Die Verwendung des ternären Operators erfordert etwas mehr Eingabe, unterscheidet jedoch deutlich zwischen dem ausgewerteten Booleschen Ausdruck und dem zugewiesenen Wert. Darüber hinaus kann es verkettet werden, sodass die oben ausgeführten Standardzuweisungstypen neu erstellt werden können.

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f =  ( a ) ? a : 
                ( b ) ? b :
                       ( c ) ? c :
                              ( d ) ? d :
                                      e;

alert(f); // 4
WSimpson
quelle
potentially be targeted for change in the future.Ja, aber das gilt nicht für Javascript.
Dadan
Kam hierher und sah alle oben genannten Antworten und dachte mir, dass etwas an der Aufgabe einfach nicht stimmte. Ich habe gerade Clean Code von Robert C Martin gelesen und diese Art der Zuweisung verstößt definitiv gegen die Regel "Keine Nebenwirkungen haben" ... während der Autor selbst angibt, dass sein Buch nur eine von vielen Techniken ist, um guten Code zu generieren, ich war immer noch überrascht, dass niemand sonst gegen diese Art von Auftrag protestierte. +1
Albert Rothman
Danke für die Antwort. Ich denke, mehr Menschen müssen beim Schreiben von Code Nebenwirkungen berücksichtigen, aber bis jemand viel Zeit damit verbracht hat, den Code anderer Leute zu pflegen. Sie denken oft nicht darüber nach.
WSimpson
1
Sie denken wirklich, dass Monstrosität klarer ist als a || b || c || d || e?
Devios1
1
@ AlbertRothman Ich sehe keine Nebenwirkungen. Nichts wird mutiert. Es ist einfach eine Abkürzung für Null-Koaleszenz, was in vielen Sprachen durchaus üblich ist.
Devios1
7

Gibt den ersten wahren Wert der Ausgabe zurück .

Wenn alle falsch sind, geben Sie den letzten falschen Wert zurück.

Beispiel:-

  null || undefined || false || 0 || 'apple'  // Return apple
Arshid KV
quelle
4

Es setzt die neue Variable ( z) entweder auf den Wert x"wahr" (nicht Null, ein gültiges Objekt / Array / Funktion / was auch immer) oder auf yandere Weise. Es ist eine relativ häufige Methode, einen Standardwert anzugeben, falls dieser xnicht vorhanden ist.

Wenn Sie beispielsweise eine Funktion haben, die einen optionalen Rückrufparameter verwendet, können Sie einen Standardrückruf bereitstellen, der nichts bewirkt:

function doSomething(data, callback) {
    callback = callback || function() {};
    // do stuff with data
    callback(); // callback will always exist
}
Matthew Crumley
quelle
1

Dies bedeutet, dass wenn xgesetzt ist, der Wert für zist x, andernfalls, wenn gesetzt yist, wird sein Wert als der zWert von gesetzt.

es ist das gleiche wie

if(x)
  z = x;
else
  z = y;

Dies ist möglich, weil logische Operatoren in JavaScript keine booleschen Werte zurückgeben, sondern den Wert des letzten Elements, das zum Abschließen der Operation benötigt wird (in einem ODER-Satz wäre dies der erste nicht falsche Wert, in einem UND-Satz der letzte ). Wenn der Vorgang fehlschlägt, falsewird er zurückgegeben.

Andris
quelle
5
das ist falsch! wenn (x) {z = x; } else {z = y;} Wenn der erste Wert falsch ist, wird der zweite Wert immer zugewiesen, unabhängig davon, was der Wert tatsächlich ist.
Evilpie
Abgesehen davon, dass ich denke, dass es z nur y zuweist, wenn x falsch ist . So funktioniert es für mich in FF natürlich, das könnte auch von der Implementierung abhängen.
Tvanfosson
7
Der letzte Teil über die Rückgabe von false ist nicht wahr (kein Wortspiel beabsichtigt). Wenn der erste Wert falsey ist, gibt der ||Operator nur den zweiten Wert zurück, unabhängig davon, ob er wahr ist oder nicht.
Matthew Crumley
-1. Ihr äquivalentes Code-Snippet ist korrekt, aber der wichtige Punkt ist, dass zder Wert festgelegt wird, xwenn dieser Wert wahr ist . Andernfalls wird der Wert auf gesetzt y. Dies bedeutet, dass wenn xzum Beispiel 0oder die leere Zeichenfolge festgelegt ist "", dies nicht das tut, was Sie sagen, da diese Werte falsch sind .
Daniel Cassidy
1

Es heißt Kurzschlussoperator.

Die Kurzschlussauswertung besagt, dass das zweite Argument nur ausgeführt oder ausgewertet wird, wenn das erste Argument nicht ausreicht, um den Wert des Ausdrucks zu bestimmen. Wenn das erste Argument der Funktion OR (||) als wahr ausgewertet wird, muss der Gesamtwert wahr sein.

Es kann auch verwendet werden, um einen Standardwert für das Funktionsargument festzulegen. "

function theSameOldFoo(name){ 
  name = name || 'Bar' ;
  console.log("My best friend's name is " + name);
}
theSameOldFoo();  // My best friend's name is Bar
theSameOldFoo('Bhaskar');  // My best friend's name is Bhaskar`
Vijay
quelle
0

Es wertet X aus und wenn X nicht null ist, die leere Zeichenfolge oder 0 (logisch falsch), wird es z zugewiesen. Wenn X null ist, die leere Zeichenfolge oder 0 (logisch falsch), wird z y zugewiesen.

var x = '';
var y = 'bob';
var z = x || y;
alert(z);

Gibt 'bob' aus;

Tvanfosson
quelle
Sie sollten klarstellen, was Sie unter "leer" verstehen. Leere Zeichenfolgen werden dazu gezwungen false, aber leere Arrays oder Objekte werden dazu gezwungen true.
Daniel Cassidy
@Daniel "null, leer oder 0" - null würde für Arrays und Objekte gelten. Punkt genommen.
Tvanfosson
0

Laut dem Blog- Beitrag von Bill Higgins ; In der logischen ODER-Zuweisungssprache Javascript (Februar 2007) gilt dieses Verhalten ab Version 1.2 (mindestens).

Er schlägt auch eine andere Verwendung dafür vor (zitiert): " leichte Normalisierung von browserübergreifenden Unterschieden "

// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
Alon Brontman
quelle