Christian Seiler: false >= null

Beitrag lesen

Hallo!

ich habe dann mal ein wenig in der dokumentation gelesen und versucht zu verstehen warum das so ist.

Der Hintergrund ist eigentlich ziemlich einfach:

null ist vom Typ null [1] und evaluiert nach:

false im Boolean-Kontext
 0 im Zahlen-Kontext
 "null" im String-Kontext

undefined ist vom Typ undefined und evaluiert nach:

false im Boolean-Kontext
 NaN im Zahlen-Kontext
 "undefined" im String-Kontext

Die Frage bleibt jetzt, wann implizite Typumwandlungen bei Vergleichen stattfinden. Und die Regeln sind wie folgt für x == y bzw. x != y, falls die Typen nicht gleich sind:

[Nummerierung an Hand ovn ECMA-262 11.9.3]
14. x ist undefined, y ist null: true
15. x ist null, y ist undefined: true
16. x ist Zahl, y ist String: Wandle y in eine Zahl um und vergleiche dann
17. x ist String, y ist Zahl: Wandle x in eine Zahl um und vergleiche dann
18. x ist Boolean, y ist etwas anderes: Wandle x in eine Zahl um und
                                        vergleiche dann
19. y ist Boolean, x ist etwas anderes: Wandle y in eine Zahl um und
                                        vergleiche dann
20. x ist String oder Zahl und y ist Objekt: Wandle y in einen primitiven
                                             Datentypen um und vergleiche
                                             dann.
21. y ist String oder Zahl und x ist Objekt: Wandle x in einen primitiven
                                             Datentypen um und vergleiche
                                             dann.
22. Wenn keines der obigen zutrifft: false

Das heißt, für null == false:

Fällt in Fall 19, also wird false in eine Zahl umgewandelt (gibt 0) und dann verglichen: null == 0. Typ null und Typ Zahl tauchen aber nicht in der obigen Liste auf, also trifft 22 zu und das Ergebnis ist false.

Für den Fall undefined == false:

Fällt in den Fall 19, also wird false in eine Zahl umgewandelt (gibt 0) und dann verglichen: undefined == 0. Typ undefined und Typ Zahl tauchen aber nicht in der obigen Liste auf, also trifft 22 zu und das Ergebnis ist false.

Betrachten wir nun die Regeln für die Vergleiche x < y, x <= y, x > y und x >= y:

Wenn x und y in primitive Datentypen gewandelt keine Strings sind, dann gelten folgende Vergleichsregeln (nach ECMA-262 11.8.5):

4. Wandle x in Zahl um
5. Wandle y in Zahl um
6. Wenn x NaN ist: gib undefined zurück
7. Wenn y NaN ist: gib undefined zurück
8. Wenn x und y die gleiche Zahl sind, gib false zurück
9. Wenn x = +0 und y = -0 ist, gib false zurück
10. Wenn x = -0 und y = +0 ist, gib false zurück
11. Wenn x = +unendlich ist, gib false zurück
12. Wenn y = +unendlich ist, gib true zurück
13. Wenn y = -unendlich ist, gib false zurück
14. Wenn x = -unendlich ist, gib true zurück
15. Führe den mathematischen Vergleich x < y durch und gib das Ergebnis
    zurück.

Das wird dann in die Operatoren "<" und ">=" so umgesetzt:

| verwend. Vergleichsoperator
Ergebnis des Vergleichs |   <   |   >=
------------------------+-------+-------
 true                   | true  | false
 false                  | false | true
 undefined              | false | false

(Bei ">" und "<=" werden nur die beiden Operatoren vertauscht.)

Betrachten wir nun den Fall null < false:

Schritt 4 wandelt null in eine Zahl um, ergibt +0. Schritt 5 wandelt false in eine Zahl um, ergibt +0. Beide sind mathematisch gleich, Fall 8, also ergibt das ganze false, false ergibt in der Lookup-Tabelle für < ein false.

Betrachten wir nun den Fall undefined < false:

Schritt 4 wandelt undefined in eine Zahl um, ergibt NaN. Schritt 5 wandelt false in eine Zahl um, ergibt +0. Fall 6 tritt ein, ergebnis ist undefined. In der Lookuptabelle ergibt sich nun für "<" das Resultat false.

Also ist null < false == false und undefined < false == false.

Betrachten wir nun den Fall null <= false - der ist identisch mit dem Fall false >= null:

Schritt 4 wandelt null in eine Zahl um, ergibt +0. Schritt 5 wandelt false in eine Zahl um, ergibt +0. Beide sind mathematisch gleich, Fall 8, also ergibt das ganze false, false ergibt in der Lookup-Tabelle für >= ein true.

Betrachten wir nun den Fall undefined <= false - der ist identisch mit dem Fall false >= undefined:

Schritt 4 wandelt undefined in eine Zahl um, ergibt NaN. Schritt 5 wandelt false in eine Zahl um, ergibt +0. Fall 6 tritt ein, ergebnis ist undefined. In der Lookuptabelle ergibt sich nun für ">=" das Resultat false.

Also ist false >= null == true und undefined >= null == false.

Das gleiche Spiel ist auch bei "" der Fall, da "" in eine Zahl gewandelt eben auch 0 ergibt (damit < und > andere Semantiken bei Stringvergleichen haben, müssen beides Strings sein).

Ich hoffe, ich konnte damit das ganze etwas verdeutlichen.

[1] typeof liefert nicht immer den internen Typ zurück!

Viele Grüße,
Christian