JavaScript – Das Handbuch für die Praxis. David Flanagan
Umwandlungen von Objekten in primitive Werte beide Operanden Strings, werden sie anhand ihrer alphabetischen Reihenfolge verglichen. Diese »alphabetische Reihenfolge« wird dabei durch die numerische Abfolge der 16-Bit-Unicode-Werte bestimmt, aus denen die Strings bestehen.
Ist nach den Umwandlungen von Objekten in primitive Werte mindestens einer der Operanden kein String, werden beide Operanden in Zahlen umgewandelt und numerisch verglichen. 0 und -0 werden als gleich betrachtet. Infinity ist größer als jede Zahl außer sich selbst, und -Infinity ist kleiner als jede Zahl außer sich selbst. Wenn einer der Operanden NaN ist (oder in diesen Wert umgewandelt wird), liefern die Vergleichsoperatoren immer false zurück. Obwohl die arithmetischen Operatoren nicht zulassen, dass BigInt-Werte mit regulären Zahlen gemischt werden, erlauben die Vergleichsoperatoren Vergleiche zwischen Zahlen und BigInts.
Denken Sie daran, dass JavaScript-Strings Folgen von 16-Bit-Ganzzahlen und String-Vergleiche nur numerische Vergleiche der in ihnen enthaltenen Werte sind. Die durch Unicode vorgegebene numerische Reihenfolge entspricht nicht notwendigerweise der traditionellen Sortierfolge, die in einer bestimmten Sprache oder einem bestimmten Gebietsschema (einer Locale) verwendet wird. Beachten Sie insbesondere, dass String-Vergleiche Groß-/Kleinschreibung berücksichtigen und dass alle ASCII-Großbuchstaben »kleiner als« alle ASCII-Kleinbuchstaben sind. Diese Regel kann zu verwirrenden Ergebnissen führen, wenn Sie auf dieses Verhalten nicht eingestellt sind. Beispielsweise würde der Operator < den String »Zoo« vor dem String »aal« einsortieren.
Einen robusteren Algorithmus für String-Vergleiche finden Sie in der Methode String.localeCompare(), die Locale-spezifische Definitionen der alphabetischen Reihenfolge berücksichtigt. Für Vergleiche, bei denen die Groß- und Kleinschreibung nicht berücksichtigt werden soll, können Sie Zeichenfolgen mit String.toLowerCase() oder String.toUpperCase() in Klein- oder Großbuchstaben konvertieren. Als allgemeineres und besser lokalisiertes Vergleichswerkzeug für Strings können Sie die in 11.7.3 beschriebene Intl.Collator-Klasse verwenden.
Der +-Operator und die Vergleichsoperatoren verhalten sich bei Zahl- und String-Operanden unterschiedlich. + bevorzugt Strings: Es wird eine Verkettung durchgeführt, wenn einer der Operanden ein String ist. Die Vergleichsoperatoren bevorzugen Zahlen und führen nur dann einen String-Vergleich durch, wenn beide Operanden Strings sind:
1 + 2 // => 3: Addition.
"1" + "2" // => "12": Verkettung.
"1" + 2 // => "12": 2 wird in "2" umgewandelt.
11 < 3 // => false: Numerischer Vergleich.
"11" < "3" // => true: String-Vergleich.
"11" < 3 // => false: Numerischer Vergleich, "11" wird in 11 umgewandelt.
"one" < 3 // => false: Numerischer Vergleich, "one" wird in NaN konvertiert.
Beachten Sie bitte auch, dass sich die Kleiner-gleich- und Größer-gleich-Operatoren <= und >= nicht auf den nicht-strikten oder strikten Gleichheitsoperator stützen, wenn sie prüfen, ob zwei Werte »gleich« sind. Stattdessen ist Kleiner-gleich einfach als »nicht größer als« und Größer-gleich als »nicht kleiner als« definiert. Die einzige Ausnahme tritt ein, wenn einer der Operanden NaN ist (oder dazu umgewandelt wird). In diesem Fall liefern alle vier Vergleichsoperatoren false.
4.9.3Der in-Operator
Der Operator in erwartet als linken Operanden einen String oder ein Symbol oder aber einen Wert, der in einen String konvertiert werden kann. Er erwartet als rechten Operanden ein Objekt. Er wird zu true ausgewertet, wenn der Wert auf der linken Seite der Name einer Eigenschaft des Objekts auf der rechten Seite ist, zum Beispiel:
let point = {x: 1, y: 1}; // Ein Objekt definieren.
"x" in point // => true: Objekt hat eine Eigenschaft namens "x".
"z" in point // => false: Objekt hat keine Eigenschaft namens "z".
"toString" in point // => true: Objekt erbt toString()-Methode.
let data = [7,8,9]; // Ein Array mit Elementen an den Indizes 0, 1 und 2.
"0" in data // => true: Array hat ein Element "0".
1 in data // => true: Zahlen werden in Strings umgewandelt.
3 in data // => false: Kein Element 3.
4.9.4Der instanceof-Operator
Der instanceof-Operator erwartet auf der linken Seite ein Objekt als Operanden und auf der rechten Seite einen Operanden, der eine Klasse von Objekten angibt. Der Operator wird zu true ausgewertet, wenn das linke Objekt eine Instanz der rechten Klasse ist, ansonsten zu false. Kapitel 9 erläutert, dass in JavaScript Klassen von Objekten durch die Konstruktorfunktionen definiert werden, mit denen Objektinstanzen initialisiert werden. Der rechte Operand sollte beim instanceof-Operator also eine Funktion sein. Hier einige Beispiele:
let d = new Date(); // Erstellt ein neues Objekt mit dem Date()-Konstruktor.
d instanceof Date // => true: d wurde mit Date() erstellt.
d instanceof Object // => true: Alle Objekte sind Instanzen von Object.
d instanceof Number // => false: d ist kein Number-Objekt.
let a = [1, 2, 3]; // Erstellt ein Array mit Array-Literal-Syntax.
a instanceof Array // => true: a ist ein Array.
a instanceof Object // => true: Alle Arrays sind Objekte.
a instanceof RegExp // => false: Arrays sind keine regulären Ausdrücke.
Beachten Sie bitte, dass alle Objekte Instanzen von Object sind. instanceof berücksichtigt auch eventuell vorhandene übergeordnete Klassen (sogenannte »Superklassen«), wenn es entscheidet, ob ein Objekt eine Instanz einer Klasse ist. Ist der linksseitige Operand von instanceof kein Objekt, liefert der Operator false. Ist die rechte Seite keine Objektklasse, wird ein TypeError ausgelöst.
Um genau zu verstehen, wie der instanceof-Operator funktioniert, müssen wir uns die »Prototypenkette« anschauen. Damit ist der Vererbungsmechanismus von JavaScript gemeint, der in 6.3.2 beschrieben wird. Im Ausdruck o instanceof f wertet JavaScript zuerst den Teilausdruck f.prototype aus und sucht dann in der Prototypenkette von o nach diesem Wert. Wenn er dort gefunden wird, ist o eine Instanz von f (oder eine Unterklasse von f), und der Operator gibt true zurück. Wenn f.prototype kein Wert in der Prototypenkette von o ist, dann ist o keine Instanz von f, und instanceof gibt false zurück.
4.10Logische Ausdrücke
Die logischen Operatoren &&, || und ! führen boolesche Operationen aus und werden häufig verwendet, um zwei relationale Ausdrücke zu einem komplexeren Ausdruck zu kombinieren. Diesen logischen Operatoren wenden wir uns in den folgenden Unterabschnitten zu. Als Hintergrund möchte ich noch einmal an das Konzept der »irgendwie wahren« bzw. nicht-strikt wahren truthy- und »irgendwie falschen« bzw. nicht-strikt falschen falsy-Werte erinnern, das in 3.4 eingeführt wurde.
4.10.1Logisches UND (&&)
Der Operator && kann auf drei verschiedenen Ebenen betrachtet werden. Auf der einfachsten Stufe, wenn er mit booleschen Operanden verwendet wird, führt && einfach eine logische UND-Operation auf beiden Werten durch. Der Operator liefert nur dann