Wir kennen viele Operatoren aus der Schule. Es handelt sich dabei um Dinge wie Addition +
, Multiplikation *
, Subtraktion -
und so weiter.
In diesem Kapitel beginnen wir mit einfachen Operatoren und konzentrieren uns dann auf JavaScript-spezifische Aspekte, die nicht von der Schularithmetik abgedeckt werden.
Bevor wir fortfahren, wollen wir uns mit der gebräuchlichen Terminologie befassen.
Ein Operand – ist das, worauf Operatoren angewendet werden. Beispielsweise gibt es bei der Multiplikation von 5 * 2
zwei Operanden: Der linke Operand ist 5
und der rechte Operand ist 2
. Manchmal werden diese „Argumente“ statt „Operanden“ genannt.
Ein Operator ist unär , wenn er einen einzelnen Operanden hat. Zum Beispiel die unäre Negation -
kehrt das Vorzeichen einer Zahl um:
sei x = 1; x = -x; alarm( x ); // -1, unäre Negation wurde angewendet
Ein Operator ist binär , wenn er zwei Operanden hat. Das gleiche Minus gibt es auch in binärer Form:
sei x = 1, y = 3; alarm( y - x ); // 2, binäres Minus subtrahiert Werte
Formal haben wir in den obigen Beispielen zwei verschiedene Operatoren, die dasselbe Symbol haben: den Negationsoperator, einen unären Operator, der das Vorzeichen umkehrt, und den Subtraktionsoperator, einen binären Operator, der eine Zahl von einer anderen subtrahiert.
Die folgenden mathematischen Operationen werden unterstützt:
Addition +
,
Subtraktion -
,
Multiplikation *
,
Abteilung /
,
Rest %
,
Potenzierung **
.
Die ersten vier sind unkompliziert, während %
und **
ein paar Worte dazu benötigen.
Der Restoperator %
hat trotz seines Aussehens nichts mit Prozenten zu tun.
Das Ergebnis von a % b
ist der Rest der ganzzahligen Division von a
durch b
.
Zum Beispiel:
alarm( 5 % 2 ); // 1, der Rest von 5 geteilt durch 2 alarm( 8 % 3 ); // 2, der Rest von 8 geteilt durch 3 alarm( 8 % 4 ); // 0, der Rest von 8 geteilt durch 4
Der Potenzierungsoperator a ** b
potenziert a
mit b
.
In der Schulmathematik schreiben wir das als a b .
Zum Beispiel:
alarm( 2 ** 2 ); // 2² = 4 alarm( 2 ** 3 ); // 2³ = 8 alarm( 2 ** 4 ); // 2⁴ = 16
Genau wie in der Mathematik ist der Potenzierungsoperator auch für nicht ganzzahlige Zahlen definiert.
Beispielsweise ist eine Quadratwurzel eine Potenzierung um ½:
alarm( 4 ** (1/2) ); // 2 (Potenz von 1/2 ist dasselbe wie eine Quadratwurzel) alarm( 8 ** (1/3) ); // 2 (Potenz von 1/3 entspricht einer Kubikwurzel)
Lernen wir die Funktionen von JavaScript-Operatoren kennen, die über die Schularithmetik hinausgehen.
Normalerweise summiert der Plusoperator +
Zahlen.
Wenn jedoch das binäre +
auf Zeichenfolgen angewendet wird, werden diese zusammengeführt (verkettet):
let s = „my“ + „string“; Warnung(en); // mystring
Beachten Sie, dass, wenn einer der Operanden eine Zeichenfolge ist, auch der andere in eine Zeichenfolge umgewandelt wird.
Zum Beispiel:
alarm( '1' + 2 ); // „12“ alarm( 2 + '1' ); // „21“
Sehen Sie, es spielt keine Rolle, ob der erste Operand eine Zeichenfolge ist oder der zweite.
Hier ist ein komplexeres Beispiel:
alarm(2 + 2 + '1' ); // „41“ und nicht „221“
Hier arbeiten die Bediener nacheinander. Das erste +
summiert zwei Zahlen, also gibt es 4
zurück, dann fügt das nächste +
die Zeichenfolge 1
hinzu, also ist es wie 4 + '1' = '41'
.
alarm('1' + 2 + 2); // „122“ und nicht „14“
Hier ist der erste Operand ein String, der Compiler behandelt die beiden anderen Operanden ebenfalls als Strings. Die 2
wird zu '1'
verkettet, also ist es wie '1' + 2 = "12"
und "12" + 2 = "122"
.
Das binäre +
ist der einzige Operator, der Zeichenfolgen auf diese Weise unterstützt. Andere arithmetische Operatoren arbeiten nur mit Zahlen und wandeln ihre Operanden immer in Zahlen um.
Hier ist die Demo für Subtraktion und Division:
alarm( 6 - '2' ); // 4, wandelt '2' in eine Zahl um alarm( '6' / '2' ); // 3, wandelt beide Operanden in Zahlen um
Das Plus +
existiert in zwei Formen: der binären Form, die wir oben verwendet haben, und der unären Form.
Das unäre Plus oder mit anderen Worten der Plusoperator +
angewendet auf einen einzelnen Wert, hat keine Auswirkung auf Zahlen. Wenn der Operand jedoch keine Zahl ist, wandelt ihn das unäre Plus in eine Zahl um.
Zum Beispiel:
// Keine Auswirkung auf Zahlen sei x = 1; alarm( +x ); // 1 sei y = -2; alarm( +y ); // -2 // Konvertiert Nichtzahlen alarm( +true); // 1 alarm( +"" ); // 0
Es macht tatsächlich das Gleiche wie Number(...)
, ist aber kürzer.
Die Notwendigkeit, Zeichenfolgen in Zahlen umzuwandeln, besteht sehr häufig. Wenn wir beispielsweise Werte aus HTML-Formularfeldern erhalten, handelt es sich normalerweise um Zeichenfolgen. Was wäre, wenn wir sie zusammenfassen wollen?
Das binäre Plus würde sie als Strings hinzufügen:
let apples = "2"; let oranges = "3"; Alert(Äpfel + Orangen); // „23“, das binäre Plus verkettet Zeichenfolgen
Wenn wir sie als Zahlen behandeln wollen, müssen wir sie umwandeln und dann summieren:
let apples = "2"; let oranges = "3"; // beide Werte vor dem binären Plus in Zahlen umgewandelt Alert( +Äpfel + +Orangen ); // 5 // die längere Variante // alarm( Zahl(Äpfel) + Zahl(Orangen) ); // 5
Aus der Sicht eines Mathematikers mag die Fülle an Pluspunkten seltsam erscheinen. Aber aus der Sicht eines Programmierers gibt es nichts Besonderes: Zuerst werden unäre Pluszeichen angewendet, sie wandeln Zeichenfolgen in Zahlen um, und dann fasst das binäre Plus sie zusammen.
Warum werden unäre Pluspunkte auf Werte vor den binären Einsen angewendet? Wie wir sehen werden, liegt das an ihrer höheren Priorität .
Wenn ein Ausdruck mehr als einen Operator hat, wird die Ausführungsreihenfolge durch deren Rangfolge definiert, oder anders ausgedrückt, durch die Standardprioritätsreihenfolge der Operatoren.
Aus der Schule wissen wir alle, dass die Multiplikation im Ausdruck 1 + 2 * 2
vor der Addition berechnet werden sollte. Genau das ist die Prioritätssache. Man sagt, dass die Multiplikation eine höhere Priorität hat als die Addition.
Klammern haben Vorrang vor allen Prioritäten. Wenn wir also mit der Standardreihenfolge nicht zufrieden sind, können wir sie verwenden, um sie zu ändern. Schreiben Sie zum Beispiel (1 + 2) * 2
.
Es gibt viele Operatoren in JavaScript. Jeder Operator hat eine entsprechende Prioritätsnummer. Derjenige mit der größeren Nummer wird zuerst ausgeführt. Bei gleicher Priorität erfolgt die Ausführungsreihenfolge von links nach rechts.
Hier ist ein Auszug aus der Rangfolgetabelle (Sie müssen sich das nicht merken, aber beachten Sie, dass unäre Operatoren höher sind als die entsprechenden binären):
Vorrang | Name | Zeichen |
---|---|---|
… | … | … |
14 | unäres Plus | + |
14 | unäre Negation | - |
13 | Potenzierung | ** |
12 | Multiplikation | * |
12 | Division | / |
11 | Zusatz | + |
11 | Subtraktion | - |
… | … | … |
2 | Abtretung | = |
… | … | … |
Wie wir sehen können, hat das „unäre Plus“ eine Priorität von 14
, was höher ist als die 11
der „Addition“ (binäres Plus). Aus diesem Grund funktionieren im Ausdruck "+apples + +oranges"
unäre Pluspunkte vor der Addition.
Beachten Sie, dass eine Zuweisung =
auch ein Operator ist. Es wird in der Rangfolgetabelle mit der sehr niedrigen Priorität 2
aufgeführt.
Deshalb werden bei der Zuweisung einer Variablen wie x = 2 * 2 + 1
zuerst die Berechnungen durchgeführt und dann =
ausgewertet und das Ergebnis in x
gespeichert.
sei x = 2 * 2 + 1; alarm( x ); // 5
Die Tatsache, dass =
ein Operator und kein „magisches“ Sprachkonstrukt ist, hat eine interessante Implikation.
Alle Operatoren in JavaScript geben einen Wert zurück. Das ist für +
und -
offensichtlich, gilt aber auch für =
.
Der Aufruf x = value
schreibt den value
in x
und gibt ihn dann zurück .
Hier ist eine Demo, die eine Zuweisung als Teil eines komplexeren Ausdrucks verwendet:
sei a = 1; sei b = 2; sei c = 3 - (a = b + 1); alarm( a ); // 3 alarm( c ); // 0
Im obigen Beispiel ist das Ergebnis des Ausdrucks (a = b + 1)
der Wert, der a
zugewiesen wurde (also 3
). Es wird dann für weitere Auswertungen verwendet.
Komischer Code, nicht wahr? Wir sollten verstehen, wie es funktioniert, denn manchmal sehen wir es in JavaScript-Bibliotheken.
Bitte schreiben Sie den Code jedoch nicht so. Solche Tricks machen den Code definitiv nicht klarer oder lesbarer.
Ein weiteres interessantes Feature ist die Möglichkeit, Zuweisungen zu verketten:
seien a, b, c; a = b = c = 2 + 2; alarm( a ); // 4 alarm( b ); // 4 alarm( c ); // 4
Verkettete Aufgaben werden von rechts nach links ausgewertet. Zuerst wird der ganz rechte Ausdruck 2 + 2
ausgewertet und dann den Variablen auf der linken Seite zugewiesen: c
, b
und a
. Am Ende haben alle Variablen einen einzigen Wert.
Auch hier ist es aus Gründen der Lesbarkeit besser, solchen Code in wenige Zeilen aufzuteilen:
c = 2 + 2; b = c; a = c;
Das ist leichter zu lesen, insbesondere wenn man den Code schnell mit dem Auge scannt.
Oft müssen wir einen Operator auf eine Variable anwenden und das neue Ergebnis in derselben Variablen speichern.
Zum Beispiel:
sei n = 2; n = n + 5; n = n * 2;
Diese Notation kann mit den Operatoren +=
und *=
verkürzt werden:
sei n = 2; n += 5; // jetzt n = 7 (dasselbe wie n = n + 5) n *= 2; // jetzt n = 14 (dasselbe wie n = n * 2) alarm( n ); // 14
Für alle arithmetischen und bitweisen Operatoren gibt es kurze „Modify-and-Assign“-Operatoren: /=
, -=
usw.
Solche Operatoren haben die gleiche Priorität wie eine normale Zuweisung und werden daher nach den meisten anderen Berechnungen ausgeführt:
sei n = 2; n *= 3 + 5; // rechter Teil wird zuerst ausgewertet, dasselbe wie n *= 8 alarm( n ); // 16
Das Erhöhen oder Verringern einer Zahl um eins gehört zu den häufigsten numerischen Operationen.
Es gibt also spezielle Operatoren dafür:
Inkrementieren ++
erhöht eine Variable um 1:
let counter = 2; counter++; // funktioniert genauso wie counter = counter + 1, ist aber kürzer alarm( counter ); // 3
Dekrementieren --
verringert eine Variable um 1:
let counter = 2; Schalter--; // funktioniert genauso wie counter = counter - 1, ist aber kürzer alarm( counter ); // 1
Wichtig:
Inkrementieren/Dekrementieren kann nur auf Variablen angewendet werden. Der Versuch, es auf einen Wert wie 5++
anzuwenden, führt zu einer Fehlermeldung.
Die Operatoren ++
und --
können entweder vor oder nach einer Variablen platziert werden.
Wenn der Operator nach der Variablen sucht, liegt sie in „Postfix-Form“ vor: counter++
.
Die „Präfixform“ liegt vor, wenn der Operator vor der Variablen steht: ++counter
.
Beide Anweisungen bewirken dasselbe: Erhöhen Sie counter
um 1
.
Gibt es einen Unterschied? Ja, aber wir können es nur sehen, wenn wir den zurückgegebenen Wert von ++/--
verwenden.
Lassen Sie uns das klären. Wie wir wissen, geben alle Operatoren einen Wert zurück. Inkrementieren/Dekrementieren ist keine Ausnahme. Die Präfixform gibt den neuen Wert zurück, während die Postfixform den alten Wert (vor dem Erhöhen/Verringern) zurückgibt.
Um den Unterschied zu sehen, hier ein Beispiel:
let counter = 1; let a = ++counter; // (*) Warnung(a); // 2
In der Zeile (*)
erhöht das Präfix ++counter
counter
und gibt den neuen Wert 2
zurück. Die alert
zeigt also 2
.
Jetzt verwenden wir die Postfix-Form:
let counter = 1; sei a = counter++; // (*) hat ++counter in counter++ geändert Warnung(a); // 1
In der Zeile (*)
erhöht das Postfix in der Form counter++
ebenfalls counter
gibt jedoch den alten Wert (vor der Erhöhung) zurück. Die alert
zeigt also 1
.
Zusammenfassend:
Wenn das Ergebnis der Inkrementierung/Dekrementierung nicht verwendet wird, gibt es keinen Unterschied in der zu verwendenden Form:
sei Zähler = 0; counter++; ++Zähler; alarm( counter ); // 2, die obigen Zeilen haben dasselbe getan
Wenn wir einen Wert erhöhen und sofort das Ergebnis des Operators verwenden möchten, benötigen wir die Präfixform:
sei Zähler = 0; alarm( ++counter ); // 1
Wenn wir einen Wert erhöhen möchten, aber seinen vorherigen Wert verwenden möchten, benötigen wir die Postfix-Form:
sei Zähler = 0; alarm( counter++ ); // 0
Inkrementieren/Dekrementieren unter anderen Operatoren
Die Operatoren ++/--
können auch innerhalb von Ausdrücken verwendet werden. Ihre Priorität ist höher als die der meisten anderen arithmetischen Operationen.
Zum Beispiel:
let counter = 1; alarm( 2 * ++counter ); // 4
Vergleichen Sie mit:
let counter = 1; alarm( 2 * counter++ ); // 2, da counter++ den „alten“ Wert zurückgibt
Obwohl technisch gesehen in Ordnung, macht eine solche Notation den Code normalerweise weniger lesbar. Eine Zeile bewirkt mehrere Dinge – nicht gut.
Beim Lesen von Code kann ein schneller „vertikaler“ Blickscan leicht etwas wie counter++
übersehen und es wird nicht offensichtlich sein, dass die Variable zugenommen hat.
Wir empfehlen einen Stil „eine Linie – eine Aktion“:
let counter = 1; alarm( 2 * counter ); counter++;
Bitweise Operatoren behandeln Argumente als 32-Bit-Ganzzahlen und arbeiten auf der Ebene ihrer binären Darstellung.
Diese Operatoren sind nicht JavaScript-spezifisch. Sie werden in den meisten Programmiersprachen unterstützt.
Die Liste der Betreiber:
UND ( &
)
ODER ( |
)
XOR ( ^
)
NICHT ( ~
)
LINKE UMSCHALTTASTE ( <<
)
RECHTSUMSCHALT ( >>
)
NULLFÜLLEN RECHTSUMSCHALT ( >>>
)
Diese Operatoren werden sehr selten verwendet, wenn wir mit Zahlen auf der untersten (bitweisen) Ebene herumspielen müssen. Wir werden diese Operatoren so schnell nicht brauchen, da sie in der Webentwicklung kaum zum Einsatz kommen, aber in einigen speziellen Bereichen, wie etwa der Kryptographie, sind sie nützlich. Bei Bedarf können Sie das Kapitel „Bitweise Operatoren“ zu MDN lesen.
Der ,
ist einer der seltensten und ungewöhnlichsten Operatoren. Manchmal wird es verwendet, um kürzeren Code zu schreiben, daher müssen wir es kennen, um zu verstehen, was vor sich geht.
Mit dem Kommaoperator können wir mehrere Ausdrücke auswerten, indem wir sie durch ein Komma ,
trennen. Jeder von ihnen wird ausgewertet, aber nur das Ergebnis des letzten wird zurückgegeben.
Zum Beispiel:
sei a = (1 + 2, 3 + 4); alarm( a ); // 7 (das Ergebnis von 3 + 4)
Hier wird der erste Ausdruck 1 + 2
ausgewertet und sein Ergebnis verworfen. Dann wird 3 + 4
ausgewertet und als Ergebnis zurückgegeben.
Komma hat eine sehr niedrige Priorität
Bitte beachten Sie, dass der Komma-Operator eine sehr niedrige Priorität hat, niedriger als =
, daher sind Klammern im obigen Beispiel wichtig.
Ohne sie: a = 1 + 2, 3 + 4
wertet zuerst +
aus, summiert die Zahlen zu a = 3, 7
, dann weist der Zuweisungsoperator =
a = 3
zu und der Rest wird ignoriert. Es ist wie (a = 1 + 2), 3 + 4
.
Warum brauchen wir einen Operator, der alles außer dem letzten Ausdruck wegwirft?
Manchmal wird es in komplexeren Konstrukten verwendet, um mehrere Aktionen in einer Zeile zusammenzufassen.
Zum Beispiel:
// drei Operationen in einer Zeile für (a = 1, b = 3, c = a * b; a < 10; a++) { ... }
Solche Tricks werden in vielen JavaScript-Frameworks verwendet. Deshalb erwähnen wir sie. Aber normalerweise verbessern sie nicht die Lesbarkeit des Codes, daher sollten wir gut darüber nachdenken, bevor wir sie verwenden.
Wichtigkeit: 5
Was sind die Endwerte aller Variablen a
, b
, c
und d
nach dem folgenden Code?
sei a = 1, b = 1; sei c = ++a; // ? sei d = b++; // ?
Die Antwort lautet:
a = 2
b = 2
c = 2
d = 1
sei a = 1, b = 1; alarm( ++a ); // 2, Präfixform gibt den neuen Wert zurück alarm( b++ ); // 1, Postfix-Formular gibt den alten Wert zurück alarm( a ); // 2, einmal erhöht alarm( b ); // 2, einmal erhöht
Wichtigkeit: 3
Was sind die Werte von a
und x
nach dem folgenden Code?
sei a = 2; sei x = 1 + (a *= 2);
Die Antwort lautet:
a = 4
(multipliziert mit 2)
x = 5
(berechnet als 1 + 4)
Wichtigkeit: 5
Was sind die Ergebnisse dieser Ausdrücke?
"" + 1 + 0 "" - 1 + 0 wahr + falsch 6 / „3“ „2“ * „3“ 4 + 5 + „px“ „$“ + 4 + 5 „4“ – 2 „4px“ – 2 " -9 " + 5 " -9 " - 5 null + 1 undefiniert + 1 " t n" - 2
Denken Sie gut nach, schreiben Sie es auf und vergleichen Sie es dann mit der Antwort.
"" + 1 + 0 = "10" // (1) "" - 1 + 0 = -1 // (2) wahr + falsch = 1 6 / „3“ = 2 „2“ * „3“ = 6 4 + 5 + „px“ = „9px“ „$“ + 4 + 5 = „45 $“ „4“ – 2 = 2 „4px“ – 2 = NaN " -9 " + 5 = " -9 5" // (3) " -9 " - 5 = -14 // (4) null + 1 = 1 // (5) undefiniert + 1 = NaN // (6) " t n" - 2 = -2 // (7)
Die Addition mit einer Zeichenfolge "" + 1
wandelt 1
in eine Zeichenfolge um: "" + 1 = "1"
, und dann haben wir "1" + 0
, die gleiche Regel wird angewendet.
Die Subtraktion -
(wie die meisten mathematischen Operationen) funktioniert nur mit Zahlen, sie wandelt eine leere Zeichenfolge ""
in 0
um.
Durch die Addition mit einer Zeichenfolge wird die Zahl 5
an die Zeichenfolge angehängt.
Die Subtraktion wandelt sich immer in Zahlen um, sodass aus " -9 "
die Zahl -9
wird (Leerzeichen um sie herum werden ignoriert).
null
wird nach der numerischen Konvertierung zu 0
.
undefined
wird nach der numerischen Konvertierung zu NaN
.
Leerzeichen werden am Anfang und Ende der Zeichenfolge abgeschnitten, wenn eine Zeichenfolge in eine Zahl umgewandelt wird. Hier besteht die gesamte Zeichenfolge aus Leerzeichen wie t
, n
und einem „normalen“ Leerzeichen dazwischen. Ähnlich wie bei einer leeren Zeichenfolge wird sie also zu 0
.
Wichtigkeit: 5
Hier ist ein Code, der den Benutzer nach zwei Zahlen fragt und deren Summe anzeigt.
Es funktioniert falsch. Die Ausgabe im folgenden Beispiel ist 12
(für Standard-Eingabeaufforderungswerte).
Warum? Repariere es. Das Ergebnis sollte 3
sein.
let a = prompt("Erste Zahl?", 1); let b = prompt("Zweite Zahl?", 2); alarm(a + b); // 12
Der Grund dafür ist, dass die Eingabeaufforderung die Benutzereingabe als Zeichenfolge zurückgibt.
Variablen haben also die Werte "1"
bzw. "2"
.
sei a = „1“; // prompt("Erste Zahl?", 1); sei b = „2“; // prompt("Zweite Zahl?", 2); alarm(a + b); // 12
Was wir tun sollten, ist, Zeichenfolgen vor +
in Zahlen umzuwandeln. Verwenden Sie beispielsweise Number()
oder stellen Sie ihnen +
voran.
Zum Beispiel direkt vor prompt
:
let a = +prompt("Erste Zahl?", 1); let b = +prompt("Zweite Zahl?", 2); alarm(a + b); // 3
Oder in der alert
:
let a = prompt("Erste Zahl?", 1); let b = prompt("Zweite Zahl?", 2); alarm(+a + +b); // 3
Verwendung von unärem und binärem +
im neuesten Code. Sieht komisch aus, nicht wahr?