Javascript scheinbare Verrücktheit [duplizieren]

8

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.

Bearbeiten

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).

    
6502 11.05.2012, 17:29
quelle

2 Antworten

8

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ück   
  •   

9.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ück      

9.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.

    
Nick Retallack 11.05.2012, 17:32
quelle
9

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. Ссылка

    
Philip Walton 11.05.2012 17:32
quelle

Tags und Links