Ausdrücke und Operatoren
Dieses Kapitel beschreibt JavaScripts Ausdrücke und Operatoren, einschließlich Zuweisungs-, Vergleichs-, arithmetische, bitweise, logische, String-, ternäre Operatoren und mehr.
Auf hoher Ebene ist ein Ausdruck eine gültige Codeeinheit, die zu einem Wert aufgelöst wird. Es gibt zwei Arten von Ausdrücken: jene mit Seiteneffekten (wie das Zuweisen von Werten) und jene, die lediglich auswerten.
Der Ausdruck x = 7
ist ein Beispiel für die erste Art. Dieser Ausdruck verwendet den =
-Operator, um den Wert sieben der Variablen x
zuzuweisen. Der Ausdruck selbst wertet sich zu 7
.
Der Ausdruck 3 + 4
ist ein Beispiel für die zweite Art. Dieser Ausdruck verwendet den +
-Operator, um 3
und 4
zu addieren und ergibt einen Wert, 7
. Ist er jedoch nicht Teil einer größeren Konstruktion (zum Beispiel einer Variablendeklaration wie const z = 3 + 4
), wird sein Ergebnis sofort verworfen — das ist normalerweise ein Programmierfehler, da die Auswertung keine Effekte erzeugt.
Wie die obigen Beispiele auch zeigen, werden alle komplexen Ausdrücke durch Operatoren verknüpft, wie =
und +
. In diesem Abschnitt werden wir die folgenden Operatoren einführen:
- Zuweisungsoperatoren
- Vergleichsoperatoren
- Arithmetische Operatoren
- Bitweise Operatoren
- Logische Operatoren
- BigInt-Operatoren
- String-Operatoren
- Bedingter (ternärer) Operator
- Komma-Operator
- Unäre Operatoren
- Relationale Operatoren
Diese Operatoren verknüpfen Operanden, die entweder von Operatoren höherer Priorität gebildet werden oder einer der grundlegenden Ausdrücke sind. Eine vollständige und detaillierte Liste von Operatoren und Ausdrücken ist auch in der Referenz verfügbar.
Die Priorität von Operatoren bestimmt die Reihenfolge, in der sie bei der Auswertung eines Ausdrucks angewandt werden. Zum Beispiel:
const x = 1 + 2 * 3;
const y = 2 * 3 + 1;
Obwohl *
und +
in unterschiedlicher Reihenfolge kommen, würden beide Ausdrücke 7
ergeben, da *
Vorrang über +
hat, sodass der *
-verkettete Ausdruck immer zuerst ausgewertet wird. Sie können die Operatorpräzedenz mit Klammern überschreiben (die einen gruppierten Ausdruck erzeugen — der grundlegende Ausdruck). Um eine vollständige Tabelle der Operatorpräzedenz sowie verschiedene Warnhinweise zu sehen, besuchen Sie die Seite Operatorpräzedenz-Referenz.
JavaScript hat sowohl binäre als auch unäre Operatoren und einen speziellen ternären Operator, den bedingten Operator. Ein binärer Operator benötigt zwei Operanden, einen vor dem Operator und einen nach dem Operator:
operand1 operator operand2
Zum Beispiel 3 + 4
oder x * y
. Diese Form wird als infix binärer Operator bezeichnet, da der Operator zwischen zwei Operanden platziert ist. Alle binären Operatoren in JavaScript sind infix.
Ein unärer Operator benötigt einen einzigen Operanden, entweder vor oder nach dem Operator:
operator operand operand operator
Zum Beispiel x++
oder ++x
. Die operator operand
-Form wird als Präfix-unärer Operator bezeichnet, und die operand operator
-Form wird als Postfix-unärer Operator bezeichnet. ++
und --
sind die einzigen Postfix-Operatoren in JavaScript — alle anderen Operatoren, wie !
, typeof
, usw., sind Präfix.
Zuweisungsoperatoren
Ein Zuweisungsoperator weist seinem linken Operanden basierend auf dem Wert seines rechten Operanden einen Wert zu.
Der einfache Zuweisungsoperator ist gleich (=
), der den Wert seines rechten Operanden seinem linken Operanden zuweist.
Das heißt, x = f()
ist ein Zuweisungsausdruck, der den Wert von f()
auf x
zuweist.
Es gibt auch zusammengesetzte Zuweisungsoperatoren, die Kurzformen für die Operationen sind, die in der folgenden Tabelle aufgelistet sind:
Name | Kurzform-Operator | Bedeutung |
---|---|---|
Zuweisung | x = f() |
x = f() |
Additionszuweisung | x += f() |
x = x + f() |
Subtraktionszuweisung | x -= f() |
x = x - f() |
Multiplikationszuweisung | x *= f() |
x = x * f() |
Divisionszuweisung | x /= f() |
x = x / f() |
Restwertzuweisung | x %= f() |
x = x % f() |
Exponentialzuweisung | x **= f() |
x = x ** f() |
Linksverschiebungszuweisung | x <<= f() |
x = x << f() |
Rechtsverschiebungszuweisung | x >>= f() |
x = x >> f() |
Nicht signierte Rechtsverschiebungszuweisung | x >>>= f() |
x = x >>> f() |
Bitweise UND-Zuweisung | x &= f() |
x = x & f() |
Bitweise XOR-Zuweisung | x ^= f() |
x = x ^ f() |
Bitweise ODER-Zuweisung | x |= f() |
x = x | f() |
Logisches UND-Zuweisung | x &&= f() |
x && (x = f()) |
Logisches ODER-Zuweisung | x ||= f() |
x || (x = f()) |
Nullish coalescing-Zuweisung | x ??= f() |
x ?? (x = f()) |
Zuweisungen zu Eigenschaften
Wenn ein Ausdruck zu einem Objekt ausgewertet wird, kann die linke Seite eines Zuweisungsausdrucks Zuweisungen zu Eigenschaften dieses Ausdrucks machen. Zum Beispiel:
const obj = {};
obj.x = 3;
console.log(obj.x); // Prints 3.
console.log(obj); // Prints { x: 3 }.
const key = "y";
obj[key] = 5;
console.log(obj[key]); // Prints 5.
console.log(obj); // Prints { x: 3, y: 5 }.
Für weitere Informationen über Objekte lesen Sie den Leitfaden zu Objekten.
Wenn ein Ausdruck nicht zu einem Objekt ausgewertet wird, dann führen Zuweisungen zu Eigenschaften dieses Ausdrucks nicht zu einer Zuweisung:
const val = 0;
val.x = 3;
console.log(val.x); // Prints undefined.
console.log(val); // Prints 0.
Im strikten Modus löst der obige Code einen Fehler aus, da man Eigenschaften nicht auf Primitiven zuweisen kann.
Es ist ein Fehler, Werte an nicht modifizierbare Eigenschaften oder an Eigenschaften eines Ausdrucks ohne Eigenschaften (null
oder undefined
) zuzuweisen.
Destrukturierung
Für komplexere Zuweisungen ist die Destrukturierung eine JavaScript-Syntax, die es ermöglicht, Daten aus Arrays oder Objekten zu extrahieren, indem eine Syntax verwendet wird, die der Konstruktion von Array- und Objekt-Literalen ähnelt.
Ohne Destrukturierung erfordert es mehrere Anweisungen, um Werte aus Arrays und Objekten zu extrahieren:
const foo = ["one", "two", "three"];
const one = foo[0];
const two = foo[1];
const three = foo[2];
Mit Destrukturierung können Sie mehrere Werte mit einer einzigen Anweisung in separate Variablen extrahieren:
const [one, two, three] = foo;
Auswertung und Verschachtelung
Im Allgemeinen werden Zuweisungen innerhalb einer Variablendeklaration verwendet (d.h. mit const
, let
oder var
) oder als eigenständige Anweisungen.
// Declares a variable x and initializes it to the result of f().
// The result of the x = f() assignment expression is discarded.
let x = f();
x = g(); // Reassigns the variable x to the result of g().
Wie andere Ausdrücke werten sich jedoch auch Zuweisungsausdrücke wie x = f()
zu einem Ergebniswert aus.
Obwohl dieser Ergebniswert in der Regel nicht verwendet wird, kann er dann von einem anderen Ausdruck verwendet werden.
Das Ketten von Zuweisungen oder das Verschachteln von Zuweisungen in anderen Ausdrücken kann zu überraschendem Verhalten führen. Aus diesem Grund wird in einigen JavaScript-Stilrichtlinien empfohlen, das Ketten oder Verschachteln von Zuweisungen zu vermeiden. Dennoch können Zuweisungsketten und Verschachtelungen manchmal vorkommen, daher ist es wichtig, verstehen zu können, wie sie funktionieren.
Durch das Ketten oder Verschachteln eines Zuweisungsausdrucks kann das Ergebnis selbst einer anderen Variablen zugewiesen werden. Es kann protokolliert, in einem Array-Literal oder Funktionsaufruf platziert werden, und so weiter.
let x;
const y = (x = f()); // Or equivalently: const y = x = f();
console.log(y); // Logs the return value of the assignment x = f().
console.log(x = f()); // Logs the return value directly.
// An assignment expression can be nested in any place
// where expressions are generally allowed,
// such as array literals' elements or as function calls' arguments.
console.log([0, x = f(), 0]);
console.log(f(0, x = f(), 0));
Das Auswertungsergebnis entspricht dem Ausdruck rechts vom =
-Zeichen in der Spalte "Bedeutung" der obigen Tabelle.
Das bedeutet, dass x = f()
sich zu dem Ergebniswert von f()
auswertet, x += f()
sich zu der resultierenden Summe x + f()
und x **= f()
zu der resultierenden Potenz x ** f()
, und so weiter.
Im Falle von logischen Zuweisungen sind x &&= f()
, x ||= f()
und x ??= f()
der Rückgabewert der logischen Operation ohne Zuweisung, also x && f()
, x || f()
und x ?? f()
entsprechend.
Beim Ketten dieser Ausdrücke ohne Klammern oder andere Gruppierungsoperatoren wie Array-Literale werden die Zuweisungsausdrücke von rechts nach links gruppiert (sie sind rechtsassoziativ), sie werden jedoch von links nach rechts ausgewertet.
Beachten Sie, dass bei allen Zuweisungsoperatoren außer =
selbst die resultierenden Werte immer auf den Werten der Operanden vor der Operation basieren.
Angenommen, die folgenden Funktionen f
und g
und die Variablen x
und y
sind deklariert worden:
function f() {
console.log("F!");
return 2;
}
function g() {
console.log("G!");
return 3;
}
let x, y;
Betrachten Sie diese drei Beispiele:
y = x = f();
y = [f(), x = g()];
x[f()] = g();
Auswertungsbeispiel 1
y = x = f()
ist äquivalent zu y = (x = f())
, weil der Zuweisungsoperator =
rechtsassoziativ ist.
Es wird jedoch von links nach rechts ausgewertet:
- Der Zuweisungsausdruck
y = x = f()
beginnt mit der Auswertung.- Das
y
auf der linken Seite dieser Zuweisung evaluiert zu einer Referenz auf die Variable namensy
. - Der Zuweisungsausdruck
x = f()
beginnt mit der Auswertung.- Das
x
auf der linken Seite dieser Zuweisung evaluiert zu einer Referenz auf die Variable namensx
. - Der Funktionsaufruf
f()
druckt "F!" in die Konsole und evaluiert dann zur Zahl2
. - Dieses
2
-Ergebnis vonf()
wirdx
zugewiesen.
- Das
- Der Zuweisungsausdruck
x = f()
ist nun mit der Auswertung fertig; sein Ergebnis ist der neue Wert vonx
, der2
ist. - Dieses
2
-Ergebnis wird wiederum auchy
zugewiesen.
- Das
- Der Zuweisungsausdruck
y = x = f()
ist nun mit der Auswertung fertig; sein Ergebnis ist der neue Wert vony
– der zufällig2
ist.x
undy
werden zu2
zugewiesen, und die Konsole hat "F!" gedruckt.
Auswertungsbeispiel 2
y = [ f(), x = g() ]
wird ebenfalls von links nach rechts ausgewertet:
- Der Zuweisungsausdruck
y = [ f(), x = g() ]
beginnt mit der Auswertung.- Das
y
auf dieser Zuweisung linke Seite evaluiert zu einer Referenz auf die Variable namensy
. - Das innere Array-Literal
[ f(), x = g() ]
beginnt mit der Auswertung.- Der Funktionsaufruf
f()
druckt "F!" in die Konsole und evaluiert dann zur Zahl2
. - Der Zuweisungsausdruck
x = g()
beginnt mit der Auswertung.- Das
x
auf dieser Zuweisung linke Seite evaluiert zu einer Referenz auf die Variable namensx
. - Der Funktionsaufruf
g()
druckt "G!" in die Konsole und evaluiert dann zur Zahl3
. - Dieses
3
-Ergebnis vong()
wirdx
zugewiesen.
- Das
- Der Zuweisungsausdruck
x = g()
ist nun mit der Auswertung fertig; sein Ergebnis ist der neue Wert vonx
, der3
ist. Dieses3
-Ergebnis wird das nächste Element im inneren Array-Literal (nach dem2
vonf()
).
- Der Funktionsaufruf
- Das innere Array-Literal
[ f(), x = g() ]
ist nun mit der Auswertung fertig; sein Ergebnis ist ein Array mit zwei Werten:[ 2, 3 ]
. - Dieses
[ 2, 3 ]
-Array wird nuny
zugewiesen.
- Das
- Der Zuweisungsausdruck
y = [ f(), x = g() ]
ist nun mit der Auswertung fertig; sein Ergebnis ist der neue Wert vony
– der zufällig[ 2, 3 ]
ist.x
wird nun zu3
zugewiesen,y
wird nun zu[ 2, 3 ]
zugewiesen, und die Konsole hat "F!" und dann "G!" gedruckt.
Auswertungsbeispiel 3
x[f()] = g()
wird ebenfalls von links nach rechts ausgewertet.
(Dieses Beispiel geht davon aus, dass x
bereits einem Objekt zugewiesen ist.
Für weitere Informationen über Objekte lesen Sie den Leitfaden zu Objekten.)
- Der Zuweisungsausdruck
x[f()] = g()
beginnt mit der Auswertung.- Der
x[f()]
-Eigenschaftszugriff auf dieser Zuweisung linke Seite beginnt mit der Auswertung.- Das
x
in diesem Eigenschaftszugriff evaluiert zu einer Referenz auf die Variable namensx
. - Dann druckt der Funktionsaufruf
f()
"F!" in die Konsole und evaluiert dann zur Zahl2
.
- Das
- Der
x[f()]
-Eigenschaftszugriff auf dieser Zuweisung hat nun die Auswertung beendet; sein Ergebnis ist eine variable Eigenschaftsreferenz:x[2]
. - Dann druckt der Funktionsaufruf
g()
"G!" in die Konsole und evaluiert dann zur Zahl3
. - Dieses
3
wird nunx[2]
zugewiesen. (Dieser Schritt wird nur erfolgreich sein, wennx
einem Objekt zugewiesen ist.)
- Der
- Der Zuweisungsausdruck
x[f()] = g()
ist nun mit der Auswertung fertig; sein Ergebnis ist der neue Wert vonx[2]
, der zufällig3
ist.x[2]
wird nun3
zugewiesen, und die Konsole hat "F!" und dann "G!" gedruckt.
Vermeiden Sie Zuweisungsketten
Das Ketten von Zuweisungen oder das Verschachteln von Zuweisungen in anderen Ausdrücken kann zu überraschendem Verhalten führen. Aus diesem Grund wird empfohlen, keine Zuweisungsketten in derselben Anweisung zu verwenden.
Insbesondere das Platzieren einer Variablenkette in einer const
, let
oder var
Anweisung funktioniert oft nicht.
Nur die äußerste/linkeste Variable würde deklariert; andere Variablen innerhalb der Zuweisungskette werden nicht von der const
/let
/var
-Anweisung deklariert.
Zum Beispiel:
const z = y = x = f();
Diese Anweisung scheint die Variablen x
, y
und z
zu deklarieren.
Tatsächlich deklariert sie jedoch nur die Variable z
.
y
und x
sind entweder ungültige Referenzen auf nicht existierende Variablen (im strikten Modus) oder, schlimmer noch, sie würden im schlampigen Modus implizit globale Variablen für x
und y
erstellen.
Vergleichsoperatoren
Ein Vergleichsoperator vergleicht seine Operanden und gibt einen logischen Wert basierend darauf zurück, ob der Vergleich wahr ist.
Die Operanden können numerische, Zeichenkettenwerte, logische oder objektbasierte Werte sein.
Zeichenketten werden basierend auf standardmäßiger lexikographischer Ordnung über Unicode-Werte verglichen.
In den meisten Fällen, wenn die beiden Operanden nicht vom gleichen Typ sind, versucht JavaScript, sie in einen passenden Typ für den Vergleich zu konvertieren.
Dieses Verhalten führt im Allgemeinen dazu, dass die Operanden numerisch verglichen werden.
Die einzigen Ausnahmen von der Typkonvertierung bei Vergleichen betreffen die Operatoren ===
und !==
, die strikte Gleichheits- und Ungleichheitsvergleiche durchführen.
Diese Operatoren versuchen nicht, die Operanden vor der Prüfung der Gleichheit so zu konvertieren, dass sie kompatibel sind.
Die folgende Tabelle beschreibt die Vergleichsoperatoren in Bezug auf diesen Beispielcode:
const var1 = 3;
const var2 = 4;
Operator | Beschreibung | Beispiele, die wahr zurückgeben |
---|---|---|
Gleich (== )
|
Gibt true zurück, wenn die Operanden gleich sind. |
3 == var1
3 == '3'
|
Ungleich (!= )
|
Gibt true zurück, wenn die Operanden nicht gleich sind. |
var1 != 4
|
Strikt gleich (=== )
|
Gibt true zurück, wenn die Operanden gleich und vom gleichen
Typ sind. Siehe auch Object.is und
Gleichheit in JS.
|
3 === var1 |
Strikt ungleich (!== )
|
Gibt true zurück, wenn die Operanden vom gleichen Typ, aber nicht gleich oder von unterschiedlichem Typ sind.
|
var1 !== "3"
|
Größer als (> )
|
Gibt true zurück, wenn der linke Operand größer als der rechte Operand ist.
|
var2 > var1
|
Größer als oder gleich
(>= )
|
Gibt true zurück, wenn der linke Operand größer als oder gleich dem rechten Operand ist.
|
var2 >= var1
|
Weniger als
(< )
|
Gibt true zurück, wenn der linke Operand kleiner als der rechte Operand ist.
|
var1 < var2
|
Kleiner als oder gleich
(<= )
|
Gibt true zurück, wenn der linke Operand kleiner als oder gleich dem rechten Operand ist.
|
var1 <= var2
|
Hinweis: =>
ist kein Vergleichsoperator, sondern die Notation
für Pfeilfunktionen.
Arithmetische Operatoren
Ein arithmetischer Operator nimmt numerische Werte (entweder Literale oder Variablen) als seine Operanden und gibt einen einzigen numerischen Wert zurück.
Die Standard-arithmetischen Operatoren sind Addition (+
), Subtraktion (-
), Multiplikation (*
) und Division (/
).
Diese Operatoren funktionieren wie in den meisten anderen Programmiersprachen, wenn sie mit Gleitkommazahlen verwendet werden (insbesondere beachten Sie, dass eine Division durch null Infinity
erzeugt). Zum Beispiel:
1 / 2; // 0.5
1 / 2 === 1.0 / 2.0; // this is true
Zusätzlich zu den Standard-arithmetischen Operationen (+
, -
, *
, /
) bietet JavaScript die in der folgenden Tabelle aufgeführten arithmetischen Operatoren:
Operator | Beschreibung | Beispiel |
---|---|---|
Rest (% )
|
Binärer Operator. Gibt den ganzzahligen Rest der Division der beiden Operanden zurück. | 12 % 5 gibt 2 zurück. |
Inkrement (++ )
|
Unärer Operator. Addiert eins zu seinem Operanden. Wenn er als Präfix-Operator verwendet wird
(++x ), gibt er den Wert seines Operanden nach dem Addieren von eins zurück;
wenn er als Postfix-Operator verwendet wird (x++ ), gibt er den Wert seines
Operanden vor dem Addieren von eins zurück.
|
Wenn x 3 ist, dann setzt ++x x auf 4
und gibt 4 zurück, während x++ 3 zurückgibt und erst dann x auf 4 setzt.
|
Dekrement (-- )
|
Unärer Operator. Zieht eins von seinem Operanden ab. Der Rückgabewert ist analog zu dem des Inkrementoperators. |
Wenn x 3 ist, dann setzt --x x auf 2
und gibt 2 zurück, während x-- 3 zurückgibt und nur dann x auf 2 setzt.
|
Unäre Negation (- )
|
Unärer Operator. Gibt die Negation seines Operanden zurück. | Wenn x 3 ist, dann gibt -x -3 zurück. |
Unäres Plus (+ )
|
Unärer Operator. Versucht, den Operanden in eine Zahl zu konvertieren, falls er es nicht schon ist. |
|
Exponentiationsoperator (** )
|
Berechnet die Potenz base zu exponent ,
also base^exponent .
|
2 ** 3 gibt 8 zurück.10 ** -1
gibt 0.1 zurück.
|
Bitweise Operatoren
Ein bitweiser Operator behandelt seine Operanden als ein Set aus 32 Bits (Nullen und Einsen), anstatt als Dezimal-, Hexadezimal- oder Oktalzahlen. Zum Beispiel hat die Dezimalzahl neun eine binäre Darstellung von 1001. Bitweise Operatoren führen ihre Operationen auf solchen binären Darstellungen aus, aber sie geben Standard-JavaScript-numerische Werte zurück.
Die folgende Tabelle fasst die JavaScript-bitweisen Operatoren zusammen.
Operator | Verwendung | Beschreibung |
---|---|---|
Bitweises UND | a & b |
Gibt eine Eins in jeder Bitposition zurück, für die die entsprechenden Bits beider Operanden Einsen sind. |
Bitweises ODER | a | b |
Gibt eine Null in jeder Bitposition zurück, für die die entsprechenden Bits beider Operanden Nullen sind. |
Bitweises XOR | a ^ b |
Gibt eine Null in jeder Bitposition zurück, für die die entsprechenden Bits gleich sind. Gibt eine Eins in jeder Bitposition zurück, für die die entsprechenden Bits unterschiedlich sind. |
Bitweises NOT | ~ a |
Invertiert die Bits seines Operanden. |
Linksschiebung | a << b |
Verschiebt a in binärer Darstellung b Stellen nach links und schiebt Nullen von rechts hinein. |
Rechtsschiebung mit Vorzeichenübertragung | a >> b |
Verschiebt a in binärer Darstellung b Stellen nach rechts und verwirft abgelegte Bits. |
Nicht signierte Rechtsschiebung | a >>> b |
Verschiebt a in binärer Darstellung b Stellen nach rechts und verwirft abgelegte Bits, schiebt Nullen von links hinein. |
Bitweise logische Operatoren
Konzepthafterweise funktionieren die bitweisen logischen Operatoren wie folgt:
-
Die Operanden werden in Zweiunddreißig-Bit-Ganze Zahlen konvertiert und durch eine Reihe von Bits (Nullen und Einsen) ausgedrückt. Zahlen mit mehr als 32 Bits verlieren ihre bedeutendsten Bits. Zum Beispiel wird die folgende Zahl mit mehr als 32 Bits in eine 32-Bit-Ganze Zahl konvertiert:
Before: 1110 0110 1111 1010 0000 0000 0000 0110 0000 0000 0001 After: 1010 0000 0000 0000 0110 0000 0000 0001
-
Jedes Bit im ersten Operanden wird mit dem entsprechenden Bit im zweiten Operanden gepaart: erstes Bit zu erstem Bit, zweites Bit zu zweitem Bit usw.
-
Der Operator wird auf jedes Bitpaar angewendet, und das Ergebnis wird bitweise konstruiert.
Zum Beispiel ist die binäre Darstellung von neun 1001, und die binäre Darstellung von fünfzehn ist 1111. Wenn die bitweisen Operatoren auf diese Werte angewendet werden, ergeben sich die folgenden Ergebnisse:
Ausdruck | Ergebnis | binale Beschreibung |
---|---|---|
15 & 9 |
9 |
1111 & 1001 = 1001 |
15 | 9 |
15 |
1111 | 1001 = 1111 |
15 ^ 9 |
6 |
1111 ^ 1001 = 0110 |
~15 |
-16 |
~ 0000 0000 … 0000 1111 = 1111 1111 … 1111 0000 |
~9 |
-10 |
~ 0000 0000 … 0000 1001 = 1111 1111 … 1111 0110 |
Beachten Sie, dass alle 32 Bits mit dem Bitweisen-NOT-Operator invertiert werden und dass Werte mit dem am meisten bedeutenden (am weitesten links gelegenen) Bit auf 1 negative Zahlen darstellen (Zweierkomplementdarstellung). ~x
ergibt denselben Wert, den auch -x - 1
ergibt.
Bitweise Verschiebeoperatoren
Die bitweisen Verschiebeoperatoren benötigen zwei Operanden: Der erste ist eine Menge, die verschoben wird, und der zweite gibt die Anzahl der Bitpositionen an, um welche der erste Operand verschoben werden soll. Die Richtung der Verschiebungsoperation wird durch den verwendeten Operator gesteuert.
Verschiebeoperatoren konvertieren ihre Operanden in Zweiunddreißig-Bit-Ganze Zahlen und geben ein Ergebnis entweder vom Typ Number
oder BigInt
zurück: Insbesondere, wenn der Typ des linken Operanden BigInt
ist, geben sie BigInt
zurück; andernfalls Number
.
Die Verschiebeoperatoren sind in der folgenden Tabelle zusammengefasst.
Operator | Beschreibung | Beispiel |
---|---|---|
Linksschiebung ( << )
|
Dieser Operator verschiebt den ersten Operanden um die angegebene Anzahl von Bits nach links. Überschüssige Bits, die nach links verschoben werden, werden verworfen. Null-Bits werden von rechts hineingeschoben. |
9<<2 ergibt 36, weil 1001 um 2 Bits nach links verschoben zu 100100 wird, was 36 ist.
|
Rechtsschiebung mit Vorzeichenübertragung (>> )
|
Dieser Operator verschiebt den ersten Operanden um die angegebene Anzahl von Bits nach rechts. Überschüssige Bits, die nach rechts verschoben werden, werden verworfen. Kopien des linksten Bits werden von links hineingeschoben. |
9>>2 ergibt 2, weil 1001 um 2 Bits nach rechts verschoben zu 10 wird, was 2 ist. Ebenso ergibt -9>>2 -3, weil das Vorzeichen erhalten bleibt.
|
Nicht signierte Rechtsschiebung (>>> )
|
Dieser Operator verschiebt den ersten Operanden um die angegebene Anzahl von Bits nach rechts. Überschüssige Bits, die nach rechts verschoben werden, werden verworfen. Null-Bits werden von links hineingeschoben. |
19>>>2 ergibt 4, weil 10011 um 2 Bits nach rechts verschoben zu 100 wird, was 4 ist. Für nicht-negative Zahlen ergeben die nicht signierte Rechtsschiebung und die Rechtsschiebung mit Vorzeichenübertragung dasselbe Ergebnis.
|
Logische Operatoren
Logische Operatoren werden typischerweise mit Booleschen Werten verwendet; wenn sie es sind, geben sie einen Booleschen Wert zurück.
Die Operatoren &&
, ||
und ??
geben jedoch tatsächlich den Wert eines der angegebenen Operanden zurück, sodass, wenn diese
Operatoren mit nicht-booleschen Werten verwendet werden, sie möglicherweise einen Nicht-Booleschen Wert zurückgeben. Daher werden sie besser als "Wertauswahloperatoren" bezeichnet.
Die logischen Operatoren sind in der folgenden Tabelle beschrieben:
Operator | Verwendung | Beschreibung |
---|---|---|
Logisches UND (&& )
|
expr1 && expr2 |
Gibt expr1 zurück, wenn es in false konvertiert werden kann;
andernfalls gibt es expr2 zurück. Wenn && mit booleschen Werten verwendet wird, gibt es true zurück, wenn beide Operanden wahr sind; andernfalls gibt es false zurück.
|
Logisches ODER (|| )
|
expr1 || expr2 |
Gibt expr1 zurück, wenn es in true konvertiert werden kann;
andernfalls gibt es expr2 zurück. Wenn || mit Booleschen Werten verwendet wird, gibt es true zurück, wenn einer der Operanden wahr ist; wenn beide falsch sind, gibt es false zurück.
|
Nullish coalescing-Operator (?? )
|
expr1 ?? expr2 |
Gibt expr1 zurück, wenn es weder null noch undefined ist; andernfalls gibt es expr2 zurück.
|
Logisches NOT (! )
|
!expr |
Gibt false zurück, wenn sein einzelner Operand in true konvertiert werden kann; andernfalls gibt es true zurück.
|
Beispiele für Ausdrücke, die in false
konvertiert werden können, sind jene, die zu null
, 0
, 0n
, NaN
, der leeren Zeichenkette (""
) oder undefined
ausgewertet werden.
Der folgende Code zeigt Beispiele für den &&
(logisches UND) Operator.
const a1 = true && true; // t && t returns true
const a2 = true && false; // t && f returns false
const a3 = false && true; // f && t returns false
const a4 = false && 3 === 4; // f && f returns false
const a5 = "Cat" && "Dog"; // t && t returns Dog
const a6 = false && "Cat"; // f && t returns false
const a7 = "Cat" && false; // t && f returns false
Der folgende Code zeigt Beispiele für den ||
(logisches ODER) Operator.
const o1 = true || true; // t || t returns true
const o2 = false || true; // f || t returns true
const o3 = true || false; // t || f returns true
const o4 = false || 3 === 4; // f || f returns false
const o5 = "Cat" || "Dog"; // t || t returns Cat
const o6 = false || "Cat"; // f || t returns Cat
const o7 = "Cat" || false; // t || f returns Cat
Der folgende Code zeigt Beispiele für den ??
(nullish coalescing) Operator.
const n1 = null ?? 1; // 1
const n2 = undefined ?? 2; // 2
const n3 = false ?? 3; // false
const n4 = 0 ?? 4; // 0
Beachten Sie, wie ??
wie ||
funktioniert, jedoch nur dann den zweiten Ausdruck zurückgibt, wenn der erste "nullish" ist, d.h. null
oder undefined
. ??
ist eine bessere Alternative als ||
für die Einstellung von Standardwerten für Werte, die möglicherweise null
oder undefined
sind, insbesondere wenn Werte wie ''
oder 0
gültige Werte sind und der Standard nicht gelten sollte.
Der folgende Code zeigt Beispiele für den !
(logisches NOT) Operator.
const n1 = !true; // !t returns false
const n2 = !false; // !f returns true
const n3 = !"Cat"; // !t returns false
Kurzschlussauswertung
Da logische Ausdrücke von links nach rechts ausgewertet werden, werden sie auf mögliche "Kurzschluss"-Auswertungen mit den folgenden Regeln getestet:
falsch && alles
wird zur falschen Auswertung kurzgeschlossen.wahr || alles
wird zur wahren Auswertung kurzgeschlossen.nichtNullish ?? alles
wird zur nicht-nullish-Auswertung kurzgeschlossen.
Die Regeln der Logik garantieren, dass diese Auswertungen immer korrekt sind. Beachten Sie, dass der alles-Teil der obigen Ausdrücke nicht ausgewertet wird, sodass Nebenwirkungen davon nicht eintreten.
BigInt-Operatoren
Die meisten Operatoren, die zwischen Zahlen verwendet werden können, können auch zwischen BigInt
-Werten verwendet werden.
// BigInt addition
const a = 1n + 2n; // 3n
// Division with BigInts round towards zero
const b = 1n / 2n; // 0n
// Bitwise operations with BigInts do not truncate either side
const c = 40000000000000000n >> 2n; // 10000000000000000n
Eine Ausnahme ist die nicht signierte Rechtsschiebung (>>>
), die für BigInt-Werte nicht definiert ist. Dies liegt daran, dass ein BigInt keine feste Breite hat und daher technisch kein "höchstes Bit" hat.
const d = 8n >>> 2n; // TypeError: BigInts have no unsigned right shift, use >> instead
BigInts und Zahlen sind nicht gegenseitig ersetzbar – Sie können sie in Berechnungen nicht mischen.
const a = 1n + 2; // TypeError: Cannot mix BigInt and other types
Dies liegt daran, dass BigInt weder eine Teilmenge noch eine Obermenge von Zahlen ist. BigInts haben eine höhere Präzision als Zahlen bei der Darstellung großer Ganzzahlen, können jedoch keine Dezimalzahlen darstellen, sodass bei der impliziten Konvertierung auf beiden Seiten Präzision verloren gehen kann. Verwenden Sie eine explizite Konvertierung, um zu signalisieren, ob Sie möchten, dass die Operation eine Zahlenoperation oder eine BigInt-Operation ist.
const a = Number(1n) + 2; // 3
const b = 1n + BigInt(2); // 3n
Sie können BigInts mit Zahlen vergleichen.
const a = 1n > 2; // false
const b = 3 > 2n; // true
String-Operatoren
Zusätzlich zu den Vergleichsoperatoren, die auf Zeichenfolgenwerte angewendet werden können, verbindet der Konkatenationsoperator (+) zwei String-Werte miteinander und gibt eine weitere Zeichenfolge zurück, die die Vereinigung der beiden Operand-Zeichenfolgen ist.
Zum Beispiel,
console.log("my " + "string"); // console logs the string "my string".
Der verkürzte Zuweisungsoperator +=
kann ebenfalls zur Verkettung von Zeichenfolgen verwendet werden.
Zum Beispiel,
let myString = "alpha";
myString += "bet"; // evaluates to "alphabet" and assigns this value to myString.
Bedingter (ternärer) Operator
Der bedingte Operator ist der einzige JavaScript-Operator, der drei Operanden verwendet. Der Operator kann basierend auf einer Bedingung einen von zwei Werten haben. Die Syntax ist:
condition ? val1 : val2
Wenn Bedingung
wahr ist, hat der Operator den Wert von val1
.
Andernfalls hat er den Wert von val2
. Sie können den bedingten Operator überall verwenden, wo Sie einen Standardoperator verwenden würden.
Zum Beispiel,
const status = age >= 18 ? "adult" : "minor";
Diese Anweisung weist der Variablen Status
den Wert "adult" zu, wenn
Alter
18 oder mehr beträgt. Andernfalls weist sie den Wert "minor" zu
Status
.
Komma-Operator
Der Komma-Operator (,
)
wertet beide seiner Operanden aus und gibt den Wert des letzten Operanden zurück.
Dieser Operator wird hauptsächlich in einer for
-Schleife verwendet, um mehrere Variablen gleichzeitig bei jedem Durchlauf der Schleife zu aktualisieren.
Es wird als schlechter Stil angesehen, ihn anderswo zu verwenden, wenn er nicht notwendig ist.
Oft können auch zwei separate Anweisungen verwendet werden und sollten das auch.
Zum Beispiel, wenn a
ein zweidimensionales Array mit 10 Elementen auf einer Seite ist, verwendet der folgende Code den Komma-Operator, um zwei Variablen gleichzeitig zu aktualisieren.
Der Code gibt die Werte der Diagonalelemente im Array aus:
const x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const a = [x, x, x, x, x];
for (let i = 0, j = 9; i <= j; i++, j--) {
// ^
console.log(`a[${i}][${j}]= ${a[i][j]}`);
}
Unäre Operatoren
Ein unärer Vorgang ist ein Vorgang mit nur einem Operanden.
delete
Der delete
Operator löscht eine Eigenschaft eines Objekts.
Die Syntax ist:
delete object.property;
delete object[propertyKey];
delete objectName[index];
wobei objekt
der Name eines Objekts ist, eigenschaft
eine vorhandene Eigenschaft ist und eigenschaftsSchlüssel
eine Zeichenkette oder ein Symbol ist, das auf eine vorhandene Eigenschaft verweist.
Wenn der delete
Operator erfolgreich ist, entfernt er die Eigenschaft aus dem Objekt.
Der Versuch, danach darauf zuzugreifen, führt zu undefined
.
Der delete
Operator gibt true
zurück, wenn der Vorgang möglich ist; er gibt false
zurück, wenn der Vorgang nicht möglich ist.
delete Math.PI; // returns false (cannot delete non-configurable properties)
const myObj = { h: 4 };
delete myObj.h; // returns true (can delete user-defined properties)
Löschen von Array-Elementen
Da Arrays einfach Objekte sind, ist es technisch möglich, Elemente daraus zu löschen
.
Dies wird jedoch als schlechte Praxis angesehen - versuchen Sie, dies zu vermeiden.
Wenn Sie eine Array-Eigenschaft löschen, wird die Array-Länge nicht beeinflusst und andere Elemente werden nicht neu indiziert.
Um dieses Verhalten zu erreichen, ist es viel besser, das Element einfach mit dem Wert undefined
zu überschreiben.
Um das Array tatsächlich zu manipulieren, verwenden Sie die verschiedenen Array-Methoden wie splice
.
typeof
Der typeof
Operator gibt eine Zeichenfolge zurück, die den Typ des nicht ausgewerteten Operanden angibt.
operand
ist die Zeichenkette, die Variablen-, Schlüsselwort- oder Objektenamen angibt, für die der Typ zurückgegeben werden soll.
Die Klammern sind optional.
Angenommen, Sie definieren die folgenden Variablen:
const myFun = () => 5 + 2;
const shape = "round";
const size = 1;
const foo = ["Apple", "Mango", "Orange"];
const today = new Date();
Der typeof
Operator gibt die folgenden Ergebnisse für diese Variablen zurück:
typeof myFun; // returns "function"
typeof shape; // returns "string"
typeof size; // returns "number"
typeof foo; // returns "object"
typeof today; // returns "object"
typeof doesntExist; // returns "undefined"
Für die Schlüsselwörter true
und null
, der typeof
Operator gibt die folgenden Ergebnisse zurück:
typeof true; // returns "boolean"
typeof null; // returns "object"
Für eine Zahl oder einen String gibt der typeof
Operator die folgenden Ergebnisse zurück:
typeof 62; // returns "number"
typeof "Hello world"; // returns "string"
Für Eigenschaftswerte gibt der typeof
Operator den Typ des
Wertes zurück, den die Eigenschaft enthält:
typeof document.lastModified; // returns "string"
typeof window.length; // returns "number"
typeof Math.LN2; // returns "number"
Für Methoden und Funktionen gibt der typeof
Operator die folgenden Ergebnisse zurück:
typeof blur; // returns "function"
typeof eval; // returns "function"
typeof parseInt; // returns "function"
typeof shape.split; // returns "function"
Für vordefinierte Objekte gibt der typeof
Operator die folgenden Ergebnisse zurück:
typeof Date; // returns "function"
typeof Function; // returns "function"
typeof Math; // returns "object"
typeof Option; // returns "function"
typeof String; // returns "function"
void
Der void
Operator spezifiziert einen Ausdruck, der ausgewertet werden soll, ohne dass ein Wert zurückgegeben wird.
expression
ist ein JavaScript-Ausdruck, der ausgewertet werden soll.
Die Klammern um den Ausdruck sind optional, aber es ist eine gute Praxis, sie zu verwenden, um Präzedenzprobleme zu vermeiden.
Relationale Operatoren
Ein Relationaler Operator vergleicht seine Operanden und gibt einen Booleschen Wert basierend darauf zurück, ob der Vergleich wahr ist.
in
Der in
Operator gibt true
zurück, wenn die angegebene Eigenschaft im angegebenen Objekt existiert.
Die Syntax ist:
propNameOrNumber in objectName
wobei propNameOrNumber
ein Zeichenfolgen-, numerischer oder Symbolausdruck ist, der einen Eigenschaftsnamen oder Array-Index darstellt, und objectName
der Name eines Objekts ist.
Die folgenden Beispiele zeigen einige Verwendungen des in
Operators.
// Arrays
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
0 in trees; // returns true
3 in trees; // returns true
6 in trees; // returns false
"bay" in trees; // returns false
// (you must specify the index number, not the value at that index)
"length" in trees; // returns true (length is an Array property)
// built-in objects
"PI" in Math; // returns true
const myString = new String("coral");
"length" in myString; // returns true
// Custom objects
const myCar = { make: "Honda", model: "Accord", year: 1998 };
"make" in myCar; // returns true
"model" in myCar; // returns true
instanceof
Der instanceof
Operator gibt true
zurück,
wenn das angegebene Objekt vom angegebenen Objekttyp ist. Die Syntax ist:
object instanceof objectType
wobei object
das Objekt ist, das gegen objectType
getestet werden soll, und objectType
ein Konstruktor ist, der einen Typ darstellt, wie Map
oder Array
.
Verwenden Sie instanceof
, wenn Sie den Typ eines Objekts zur Laufzeit bestätigen müssen.
Zum Beispiel, wenn Sie Ausnahmen abfangen, können Sie zu anderem Ausnahmebehandlungscode verzweigen, abhängig vom Typ der geworfenen Ausnahme.
Zum Beispiel verwendet der folgende Code instanceof
, um festzustellen, ob obj
ein Map
-Objekt ist. Da obj
ein Map
-Objekt ist, werden die Anweisungen innerhalb des if
-Blocks ausgeführt.
const obj = new Map();
if (obj instanceof Map) {
// statements to execute
}
Grundlegende Ausdrücke
Alle Operatoren operieren schließlich auf einem oder mehreren grundlegenden Ausdrücken. Diese grundlegenden Ausdrücke schließen Bezeichner und Literale ein, aber es gibt auch einige andere Arten. Sie werden unten kurz eingeführt und ihre Semantik wird in ihren jeweiligen Referenzabschnitten detailliert beschrieben.
this
Verwenden Sie das this
Schlüsselwort, um auf das aktuelle Objekt zu verweisen.
Im Allgemeinen bezieht sich this
auf das aufrufende Objekt in einer Methode.
Verwenden Sie this
entweder mit der Punkt- oder der Klammernotation:
this["propertyName"];
this.propertyName;
Angenommen, eine Funktion namens validate
validiert die value
-Eigenschaft eines Objekts, wobei das Objekt sowie die hohen und niedrigen Werte angegeben werden:
function validate(obj, lowVal, highVal) {
if (obj.value < lowVal || obj.value > highVal) {
console.log("Invalid Value!");
}
}
Sie können validate
in jedem onChange
-Ereignis-Handler des Formularelements aufrufen, indem Sie this
verwenden, um es an das Formularelement zu übergeben, wie im folgenden Beispiel:
<p>Enter a number between 18 and 99:</p>
<input type="text" name="age" size="3" onChange="validate(this, 18, 99);" />
Gruppierungsoperator
Der Gruppierungsoperator ( )
steuert die Vorrangordnung der Auswertung in
Ausdrücken. Zum Beispiel können Sie Multiplikation und Division überschreiben, dann
Addition und Subtraktion, um als erstes die Addition auszuwerten.
const a = 1;
const b = 2;
const c = 3;
// default precedence
a + b * c; // 7
// evaluated by default like this
a + (b * c); // 7
// now overriding precedence
// addition before multiplication
(a + b) * c; // 9
// which is equivalent to
a * c + b * c; // 9
Eigenschaftszugriff
Die Eigenschaftszugriffssyntax erhält Eigenschaftswerte von Objekten, entweder mit Punktnotation oder mit Klammernotation.
object.property;
object["property"];
Der Leitfaden zum Arbeiten mit Objekten bietet detailliertere Informationen über Objekteigenschaften.
Optionale Verkettung
Die optionale Verkettung-Syntax (?.
) führt die verkettete Operation an einem Objekt aus, wenn es definiert und nicht null
ist und bricht ansonsten die Operation ab und gibt undefined
zurück.
Dies ermöglicht es Ihnen, auf einen Wert zuzugreifen, der null
oder undefined
sein könnte, ohne einen TypeError
zu verursachen.
maybeObject?.property;
maybeObject?.[property];
maybeFunction?.();
new
Sie können den new
Operator verwenden, um eine Instanz eines benutzerdefinierten Objekttyps oder eines der eingebauten Objekttypen zu erstellen. Verwenden Sie new
wie folgt:
const objectName = new ObjectType(param1, param2, /* …, */ paramN);
super
Das super
Schlüsselwort wird verwendet, um Funktionen auf dem Elternobjekt eines Objekts aufzurufen.
Es ist nützlich bei Klassen, um beispielsweise den Elternkonstruktor aufzurufen.
super(args); // calls the parent constructor.
super.functionOnParent(args);