Was ist der Grund für die Tatsache, dass
%Vor% gibt [true, 1]
zurück?
Mit anderen Worten, eine leere Liste ist in einem booleschen Kontext logisch wahr, ist aber gleich false
.
Ich weiß, dass die Verwendung von ===
das Problem löst, aber was ist die Erklärung für diese scheinbar völlig unlogische Wahl?
Mit anderen Worten, dies ist ein Fehler in der Sprache, etwas unbeabsichtigtes, das gerade passiert ist und das nicht behoben werden kann, weil es zu spät ist oder wirklich in der Gestaltung der Sprache, die jemand für cool hielt, um diese Art von scheinbarem Wahnsinn zu haben Ich bin mir sicher, ist für viele Programmierer ziemlich verwirrend?
Die technische Erklärung, wie dies geschieht, ist gleichzeitig erstaunlich und erschreckend, ich war jedoch mehr daran interessiert, was hinter diesem Design steckt.
Ich habe eine sehr detaillierte Erklärung von Nick Retallack akzeptiert, auch wenn es nur um die technischen Gründe dafür geht, dass []==false
wahr ist: Es ist überraschend, dass []
in einen String konvertiert und ein leerer String ein numerischer Wert ist special cased to 0 statt der scheinbar logischeren NaN
. Bei einem leeren Objekt zum Beispiel gibt der Vergleich ({}) == false
den Wert false zurück, da die Zeichenfolgendarstellung eines leeren Objekts nicht die leere Zeichenfolge ist.
Meine Neugier bleibt immer noch bei all dem, was unvorhergesehen ist (und jetzt unglücklicherweise in einem Standard verfestigt ist).
Lass uns technisch werden. Ich werde die Logik mit Zitaten aus dem ECMAScript Standard 262 erklären.
Der Ausdruck [] ? 1 : 2
ist sehr einfach:
11.12 Bedingter Operator (?:)
- Sei lref das Ergebnis der Auswertung von LogicalORExpression.
- Wenn ToBoolean (GetValue (lref)) wahr ist, dann
- Lassen Sie trueRef das Ergebnis der Auswertung der ersten AssignmentExpression sein.
- Gibt GetValue (trueRef) zurück.
- Sonst
- Lassen Sie falseRef das Ergebnis der Auswertung der zweiten AssignmentExpression sein.
- Gibt GetValue (falseRef)
zurück9.2 ToBoolean
- Nicht definiert: falsch
- Null: falsch
- Boolean: Das Ergebnis entspricht dem Eingabeargument (keine Konvertierung).
- Number: Das Ergebnis ist false, wenn das Argument +0, 0 oder NaN ist; Ansonsten ist das Ergebnis wahr.
- String: Das Ergebnis ist falsch, wenn der Argument ist der leere String (seine Länge ist Null); ansonsten der Ergebnis ist wahr.
- Objekt: true
Also ist es wahr.
Jetzt für die wilde Fahrt von dem, was passiert, wenn Sie den Doppelgleichheitsoperator verwenden. Vielleicht wird dies erklären, warum Sie das nie tun sollten.
Das Verhalten von == wird in Abschnitt 11.9.3: Der abstrakte Gleichheitsvergleichsalgorithmus erklärt.
Für x == y mit x = [] und y = false geschieht dies:
11.9.3: Der abstrakte Gleichheitsvergleichsalgorithmus
Wenn Typ (y) boolesch ist, gebe das Ergebnis des Vergleichs x == ToNumber (y)
zurück9.3 ToNumber
Das Ergebnis ist +0 , wenn das Argument ist false .
Jetzt haben wir [] == 0
11.9.3: Der abstrakte Gleichheitsvergleichsalgorithmus
Wenn Typ (x) Objekt und Typ (y) entweder Zeichenfolge oder Zahl ist, zurückgeben das Ergebnis des Vergleichs ToPrimitive (x) == y .
9.1 ToPrimitive
Gibt einen Standardwert für das Objekt zurück. Der Standardwert eines Objekts wird abgerufen, indem die interne Methode [[DefaultValue]] aufgerufen wird Objekt und übergibt den optionalen Hinweis PreferredType. Das Verhalten von Die interne Methode [[DefaultValue]] ist durch diese Spezifikation definiert für alle nativen ECMAScript-Objekte in 8.12.8.
8.12.8 DefaultValue:
Wenn die interne Methode [[DefaultValue]] von O mit Nein aufgerufen wird Hinweis, dann verhält es sich so, als wäre der Hinweis Nummer
- Sei valueOf das Ergebnis des Aufrufs der internen Methode [[Get]] des Objekts O mit dem Argument "valueOf".
- Wenn IsCallable (valueOf) wahr ist,
- Sei val das Ergebnis des Aufrufs der [[Call]] internen Methode von valueOf, mit O als this Wert und einer leeren Argumentliste.
- Wenn val ein primitiver Wert ist, gebe val
zurück- Sei toString das Ergebnis des Aufrufs der internen Methode [[Get]] des Objekts O mit dem Argument "toString".
- Wenn IsCallable (toString) wahr ist,
- Sei str das Ergebnis des Aufrufs der internen Methode [[Call]] von toString , wobei O der this-Wert und eine leere Argumentliste ist.
- Wenn str ein primitiver Wert ist, return str .
Ich gehe davon aus, dass valueOf zuerst versucht und dann zurückweist, weil das Ergebnis das gleiche Array ist, mit dem Sie begonnen haben. Dann ruft er toString on Array auf, das allgemein als kommagetrennte Liste seiner Werte implementiert wird. Für leere Arrays wie dieses, die zu einem leeren String führen.
Jetzt haben wir '' == 0
11.9.3: Der abstrakte Gleichheitsvergleichsalgorithmus
Wenn Typ (x) eine Zeichenfolge und Typ (y) eine Zahl ist, geben Sie das Ergebnis der Zeichenfolge zurück Vergleich ToNumber (x) == y
9.3.1 ToNumber, angewendet auf den String-Typ
Ein StringNumericLiteral, der leer ist oder nur Leerraum enthält ist konvertiert zu +0 .
Jetzt haben wir 0 == 0
11.9.3: Der abstrakte Gleichheitsvergleichsalgorithmus
Wenn x derselbe Zahlenwert wie y ist, geben Sie true
zurück
Super. Das ist wahr. Ziemlich verworrene Art, hierher zu kommen.
Die Verwirrung hier ist um die Definition von "Falsy" in JavaScript, die (entgegen der landläufigen Meinung) ist nicht das gleiche wie == false
.
Falsy bezieht sich eigentlich auf einen Wert, der ein boolesches Äquivalent von false hat, und nicht auf einen Ausdruck, dessen Ergebnis == false ist. Die einzigen Falsy-Werte in JavaScript sind: false
, 0
, ""
, null
, undefined
und NaN
. Also ist jeder dieser Werte - oder jeder Ausdruck, der zu einem dieser Werte zählt (wie in einem if
statment oder unter Verwendung des ternären Operators) - falsy.
Hier ist eine Tabelle, die ich aus Falsy / Truthy-Werten in JavaScript zusammensetze, die helfen sollten, dieses ganze Problem zu erklären. Ссылка
Tags und Links javascript language-design