Operator
Klassische echte Fragen
- Unter welchen Umständen wird im folgenden Code die Ausgabeanweisung ausgeführt und 1 ausgegeben ?
var a = ?;
if(a == 1 && a == 2 && a == 3){
console.log(1);
}
1. Arithmetische Operatoren
JavaScript bietet insgesamt 10 arithmetische Operatoren zur Vervollständigung grundlegender arithmetischer Operationen.
- Additionsoperator :
x + y
- Subtraktionsoperator :
x - y
- Multiplikationsoperator :
x * y
- Divisionsbetreiber :
x / y
- Exponentialoperator :
x ** y
- Restbetreiber :
x % y
- Inkrementoperator :
++x
oderx++
- Dekrementoperator :
--x
oderx--
- Numerische Operatoren :
+x
- Negative numerische Operatoren :
-x
Subtraktions-, Multiplikations- und Divisionsoperationen sind relativ einfach, dh die Durchführung entsprechender mathematischer Operationen.
Im Folgenden werden mehrere andere arithmetische Operatoren beschrieben, wobei der Schwerpunkt auf dem Additionsoperator liegt.
Additionsoperator
(1) Grundregeln
Der Additionsoperator ( +
) ist der am häufigsten verwendete Operator, um die Summe zweier Zahlen zu ermitteln.
1 + 1 // 2
JavaScript ermöglicht nicht-numerische Additionen.
true + true // 2
1 + true // 2
Im obigen Code ist die erste Zeile die Addition zweier boolescher Werte und die zweite Zeile die Addition des Werts und des booleschen Werts. In beiden Fällen werden die booleschen Werte automatisch in numerische Werte umgewandelt und anschließend addiert.
Das Besondere daran ist, dass beim Hinzufügen von zwei Zeichenfolgen der Additionsoperator zu einem Verkettungsoperator wird, der eine neue Zeichenfolge zurückgibt und die beiden ursprünglichen Zeichenfolgen verkettet.
'a' + 'bc' // "abc"
Wenn ein Operator ein String und der andere ein Nicht-String ist, wird der Nicht-String in einen String konvertiert und verkettet.
1 + 'a' // "1a"
false + 'a' // "falsea"
Der Additionsoperator entscheidet zur Laufzeit, ob eine Addition oder eine Verbindung durchgeführt wird. Mit anderen Worten: Unterschiedliche Operatoren führen zu unterschiedlichem grammatikalischem Verhalten. Dieses Phänomen wird als „Überladung“ bezeichnet. Da der Additionsoperator überladen ist, führt er möglicherweise zwei Operationen aus. Sie müssen daher bei der Verwendung vorsichtig sein.
'3' + 4 + 5 // "345"
3 + 4 + '5' // "75"
Im obigen Code führen unterschiedliche Positionen der Zeichenfolge aufgrund der Reihenfolge der Operationen von links nach rechts zu unterschiedlichen Ergebnissen.
Mit Ausnahme des Additionsoperators werden andere arithmetische Operatoren (z. B. Subtraktion, Division und Multiplikation) nicht überladen. Ihre Regeln lauten: Alle Operatoren werden in numerische Werte umgewandelt und dann werden die entsprechenden mathematischen Operationen ausgeführt.
1 - '2' // -1
1 * '2' // 2
1 / '2' // 0.5
Im obigen Code konvertieren die Subtraktions-, Divisions- und Multiplikationsoperatoren Zeichenfolgen automatisch in numerische Werte und führen dann Operationen aus.
(2) Hinzufügen von Objekten
Wenn der Operator ein Objekt ist, muss er vor dem Hinzufügen in einen primitiven Typwert konvertiert werden.
var obj = {
p: 1 };
obj + 2 // "[object Object]2"
Im obigen Code obj
lautet der Wert des in den ursprünglichen Typ konvertierten Objekts [object Object]
, und wenn es hinzugefügt wird, 2
wird das obige Ergebnis erhalten.
Das Objekt wird gemäß den folgenden Regeln in einen primitiven Typwert umgewandelt.
Zunächst werden die Methoden des Objekts valueOf
automatisch aufgerufen.
var obj = {
p: 1 };
obj.valueOf() // { p: 1 }
Im Allgemeinen gibt die valueOf
Methode des Objekts immer das Objekt selbst zurück. Zu diesem Zeitpunkt wird die Methode des Objekts automatisch aufgerufen toString
und in eine Zeichenfolge konvertiert.
var obj = {
p: 1 };
obj.valueOf().toString() // "[object Object]"
Die Methoden des Objekts toString
geben standardmäßig zurück [object Object]
, sodass das Ergebnis des vorherigen Beispiels erhalten wird.
Nachdem Sie diese Regel kennen, können Sie Ihre eigenen valueOf
Methoden oder toString
Methoden definieren, um die gewünschten Ergebnisse zu erzielen.
var obj = {
valueOf: function () {
return 1;
}
};
obj + 2 // 3
Im obigen Code haben wir die Methode obj
des zurückzugebenden Objekts definiert , also haben wir es bekommen . Da die Methode in diesem Beispiel direkt einen primitiven Typwert zurückgibt, wird die Methode nicht mehr aufgerufen.valueOf
1
obj + 2
3
valueOf
toString
Unten finden Sie ein Beispiel für eine benutzerdefinierte toString
Methode.
var obj = {
toString: function () {
return 'hello';
}
};
obj + 2 // "hello2"
Im obigen Code gibt die Objektmethode obj
einen toString
String zurück hello
. Wie bereits erwähnt, wird der Additionsoperator zum Verbindungsoperator und gibt die verbundene Zeichenfolge zurück, solange ein Operator eine Zeichenfolge ist.
Hier gibt es einen Sonderfall: Wenn der Operator eine Date
Instanz eines Objekts ist, toString
wird zuerst die Methode ausgeführt.
var obj = new Date();
obj.valueOf = function () {
return 1 };
obj.toString = function () {
return 'hello' };
obj + 2 // "hello2"
Im obigen Code obj
ist das Objekt eine Instanz eines Objekts, und die Methoden und Methoden Date
werden angepasst und die Ergebnismethode wird zuerst ausgeführt.valueOf
toString
toString
Restoperator
Der Restoperator ( %
) gibt den Rest zurück, der sich aus der Division des vorherigen Operators durch den nächsten Operator ergibt.
12 % 5 // 2
Es ist zu beachten, dass das Vorzeichen des Operationsergebnisses durch das Vorzeichen des ersten Operators bestimmt wird.
-1 % 2 // -1
1 % -2 // 1
Um also den korrekten Restwert für eine negative Zahl zu erhalten, können Sie zunächst die Absolutwertfunktion verwenden.
// 错误的写法
function isOdd(n) {
return n % 2 === 1;
}
isOdd(-5) // false
isOdd(-4) // false
// 正确的写法
function isOdd(n) {
return Math.abs(n % 2) === 1;
}
isOdd(-5) // true
isOdd(-4) // false
Der Restoperator kann auch für Gleitkommaarithmetik verwendet werden. Da Gleitkommazahlen jedoch keine exakten Werte sind, können keine völlig genauen Ergebnisse erzielt werden.
6.5 % 2.1
// 0.19999999999999973
Inkrement- und Dekrementoperatoren
Die Inkrementierungs- und Dekrementierungsoperatoren sind unäre Operatoren und erfordern nur einen Operator. Ihre Funktion besteht darin, den Operator zunächst in einen numerischen Wert umzuwandeln und dann 1 zu addieren oder 1 zu subtrahieren. Sie ändern die ursprüngliche Variable.
var x = 1;
++x // 2
x // 2
--x // 1
x // 1
Nachdem die Variable im obigen Code x
inkrementiert wurde, gibt sie zurück 2
, dekrementiert sich dann selbst und gibt zurück 1
. In beiden Fällen x
ändert sich der Wert der ursprünglichen Variablen.
Nach einer Operation ändert sich der Wert der Variablen. Dieser Effekt wird als Nebeneffekt der Operation bezeichnet. Die Inkrementierungs- und Dekrementierungsoperatoren sind die einzigen beiden Operatoren, die Nebenwirkungen haben, und keiner der anderen Operatoren ändert den Wert der Variablen.
Bei den Selbstinkrementierungs- und Selbstdekrementierungsoperatoren ist eines zu beachten: Nachdem die Variable platziert wurde, wird zuerst der Wert vor der Variablenoperation zurückgegeben und dann die Selbstinkrementierungs-/Selbstdekrementierungsoperation Vor der Variablen wird zuerst die Selbstinkrementierung/Selbstdekrementierung durchgeführt. Subtraktionsoperation, und dann wird der Wert nach der Variablenoperation zurückgegeben.
var x = 1;
var y = 1;
x++ // 1
++y // 2
Im obigen Code x
wird zuerst der aktuelle Wert zurückgegeben und dann erhöht, sodass wir erhalten 1
. y
Zuerst wird er erhöht, und dann wird der neue Wert zurückgegeben, sodass wir erhalten 2
.
numerischer Operator, negativer numerischer Operator
Der numerische Operator ( +
) verwendet ebenfalls das Pluszeichen, ist jedoch ein unärer Operator (der nur einen Operanden erfordert), während der Additionsoperator ein binärer Operator ist (der zwei Operanden erfordert).
Numerische Operatoren werden verwendet, um einen beliebigen Wert in einen numerischen Wert umzuwandeln ( Number
wie Funktionen).
+true // 1
+[] // 0
+{
} // NaN
Der obige Code zeigt an, dass nicht numerische Werte nach Durchlaufen numerischer Operatoren zu numerischen Werten werden (die letzte Zeile NaN
ist ebenfalls ein numerischer Wert). Spezifische Typkonvertierungsregeln finden Sie im Kapitel „Datentypkonvertierung“.
Der negative numerische Operator ( -
) hat ebenfalls die Funktion, einen Wert in einen numerischen Wert umzuwandeln, der erhaltene Wert ist jedoch positiv und negativ. Die gemeinsame Verwendung zweier negativer numerischer Operatoren entspricht numerischen Operatoren.
var x = 1;
-x // -1
-(-x) // 1
Die Klammern in der letzten Zeile des obigen Codes sind wichtig, sonst wird es zu einem Dekrementoperator.
Sowohl der numerische Operator als auch der negative numerische Operator geben einen neuen Wert zurück, ohne den Wert der ursprünglichen Variablen zu ändern.
Exponentialoperator
Der Exponentenoperator ( **
) schließt die Exponentialoperation ab. Der erstere Operator ist die Basis und der letztere Operator ist der Exponent.
2 ** 4 // 16
Beachten Sie, dass der Exponentenoperator rechtsassoziativ und nicht linksassoziativ ist. Das heißt, wenn mehrere Exponentenoperatoren zusammen verwendet werden, wird die Berechnung ganz rechts zuerst durchgeführt.
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512
Da im obigen Code der Exponentialoperator rechtsassoziativ ist, wird der zweite Exponentialoperator zuerst berechnet, nicht der erste.
Aufgabenverwalter
Zuweisungsoperatoren werden verwendet, um Variablen Werte zuzuweisen.
Der gebräuchlichste Zuweisungsoperator ist natürlich das Gleichheitszeichen ( =
).
// 将 1 赋值给变量 x
var x = 1;
// 将变量 y 的值赋值给变量 x
var x = y;
Der Zuweisungsoperator kann auch mit anderen Operatoren zu Variationen kombiniert werden. Unten ist die Kombination mit arithmetischen Operatoren.
// 等同于 x = x + y
x += y
// 等同于 x = x - y
x -= y
// 等同于 x = x * y
x *= y
// 等同于 x = x / y
x /= y
// 等同于 x = x % y
x %= y
// 等同于 x = x ** y
x **= y
Das Folgende ist eine Kombination mit bitweisen Operatoren (für bitweise Operatoren siehe die Einleitung später).
// 等同于 x = x >> y
x >>= y
// 等同于 x = x << y
x <<= y
// 等同于 x = x >>> y
x >>>= y
// 等同于 x = x & y
x &= y
// 等同于 x = x | y
x |= y
// 等同于 x = x ^ y
x ^= y
Diese zusammengesetzten Zuweisungsoperatoren führen zunächst die angegebene Operation aus und geben dann den erhaltenen Wert an die Variable auf der linken Seite zurück.
2. Vergleichsoperatoren
Vergleichsoperatoren werden verwendet, um die Größe zweier Werte zu vergleichen und dann einen booleschen Wert zurückzugeben, der angibt, ob die angegebene Bedingung erfüllt ist.
2 > 1 // true
Der obige Code vergleicht 2
, ob er größer als ist oder nicht, 1
und gibt zurück true
.
Beachten Sie, dass Vergleichsoperatoren Werte aller Art vergleichen können, nicht nur numerische Werte.
JavaScript bietet insgesamt 8 Vergleichsoperatoren.
>
größer als Operator<
weniger als Betreiber<=
kleiner oder gleich dem Operator>=
Größer oder gleich dem Operator==
Gleichheitsoperator===
strikter Gleichheitsoperator!=
Ungleichheitsoperator!==
strikter Ungleichheitsoperator
Diese acht Vergleichsoperatoren sind in zwei Kategorien unterteilt: Gleichheitsvergleich und Nichtgleichheitsvergleich. Die Regeln der beiden sind unterschiedlich. Bei ungleichen Vergleichen prüft der Algorithmus zunächst, ob die beiden Operatoren beide Zeichenfolgen sind. Wenn ja, vergleichen Sie sie in Wörterbuchreihenfolge (wobei tatsächlich Unicode-Codepunkte verglichen werden); andernfalls wandeln Sie beide Operatoren in numerische Werte um , und vergleichen Sie dann die numerischen Werte.
Ungleichheitsoperator: Vergleich von Zeichenfolgen
Zeichenfolgen werden in lexikografischer Reihenfolge verglichen.
'cat' > 'dog' // false
'cat' > 'catalog' // false
Die JavaScript-Engine vergleicht intern zunächst den Unicode-Codepunkt des ersten Zeichens. Wenn sie gleich sind, vergleichen Sie den Unicode-Codepunkt des zweiten Zeichens usw.
'cat' > 'Cat' // true'
Im obigen Code ist der c
Unicode-Codepunkt ( 99
) in Kleinbuchstaben größer als der C
Unicode-Codepunkt ( 67
) in Großbuchstaben und wird daher zurückgegeben true
.
Da alle Zeichen über Unicode-Codepunkte verfügen, können auch chinesische Zeichen verglichen werden.
'大' > '小' // false
Im obigen Code ist der „große“ Unicode-Codepunkt 22823 und der „kleine“ 23567, daher wird er zurückgegeben false
.
Ungleichheitsoperator: Vergleich von Nicht-Strings
Wenn mindestens einer der beiden Operatoren keine Zeichenfolge ist, muss er in die folgenden zwei Situationen unterteilt werden.
(1) Wert des primitiven Typs
Wenn es sich bei beiden Operatoren um Werte vom primitiven Typ handelt, werden sie zunächst in numerische Werte umgewandelt und dann verglichen.
5 > '4' // true
// 等同于 5 > Number('4')
// 即 5 > 4
true > false // true
// 等同于 Number(true) > Number(false)
// 即 1 > 0
2 > true // true
// 等同于 2 > Number(true)
// 即 2 > 1
Im obigen Code werden Zeichenfolgen und boolesche Werte zunächst in numerische Werte umgewandelt und dann verglichen.
NaN
Hier müssen Sie auf den Vergleich mit achten . Jeder Wert (einschließlich NaN
sich selbst), der NaN
mit dem Ungleichheitsoperator verglichen wird, wird zurückgegeben false
.
1 > NaN // false
1 <= NaN // false
'1' > NaN // false
'1' <= NaN // false
NaN > NaN // false
NaN <= NaN // false
(2) Objekt
Wenn der Operator ein Objekt ist, wird er in einen primitiven Typwert konvertiert und dann verglichen.
Um ein Objekt in einen Wert eines primitiven Typs umzuwandeln, muss der Algorithmus zunächst valueOf
die Methode aufrufen. Wenn das zurückgegebene Objekt noch ein Objekt ist, rufen Sie die toString
Methode auf. Eine ausführliche Erklärung finden Sie im Kapitel „Datentypkonvertierung“.
var x = [2];
x > '11' // true
// 等同于 [2].valueOf().toString() > '11'
// 即 '2' > '11'
x.valueOf = function () {
return '1' };
x > '11' // false
// 等同于 [2].valueOf() > '11'
// 即 '1' > '11'
Das Gleiche gilt für Vergleiche zwischen zwei Objekten.
[2] > [1] // true
// 等同于 [2].valueOf().toString() > [1].valueOf().toString()
// 即 '2' > '1'
[2] > [11] // true
// 等同于 [2].valueOf().toString() > [11].valueOf().toString()
// 即 '2' > '11'
{
x: 2 } >= {
x: 1 } // true
// 等同于 { x: 2 }.valueOf().toString() >= { x: 1 }.valueOf().toString()
// 即 '[object Object]' >= '[object Object]'
strikter Gleichheitsoperator
JavaScript bietet zwei Gleichheitsoperatoren: ==
und ===
.
Einfach ausgedrückt besteht der Unterschied zwischen ihnen darin, dass der Gleichheitsoperator ( ==
) vergleicht, ob zwei Werte gleich sind, und der strikte Gleichheitsoperator ( ===
) vergleicht, ob sie „den gleichen Wert“ haben. Wenn die beiden Werte nicht vom gleichen Typ sind, gibt der strikte Gleichheitsoperator ( ===
) sie direkt zurück false
, während der Gleichheitsoperator ( ==
) sie in denselben Typ konvertiert und dann den strikten Gleichheitsoperator zum Vergleich verwendet.
(1) Verschiedene Arten von Werten
Wenn die beiden Werte unterschiedlichen Typs sind, geben Sie sie direkt zurück false
.
1 === "1" // false
true === "true" // false
Der obige Code vergleicht den numerischen Wert 1
mit der Zeichenfolge „1“ und den booleschen Wert true
mit der Zeichenfolge "true"
. Da die Typen unterschiedlich sind, sind die Ergebnisse beide false
.
(2) Primitive Typwerte derselben Klasse
Beim Vergleich primitiver Typwerte (numerische Werte, Zeichenfolgen, boolesche Werte) desselben Typs werden die Werte zurückgegeben, wenn sie gleich sind. true
Wenn die Werte unterschiedlich sind, werden sie zurückgegeben false
.
1 === 0x1 // true
Der obige Code vergleicht Dezimal- 1
und Hexadezimalzahlen 1
und gibt sie zurück, da Typ und Wert gleich sind true
.
Es ist zu beachten, dass es NaN
keinem Wert entspricht (einschließlich sich selbst). Außerdem ist positiv 0
gleich negativ 0
.
NaN === NaN // false
+0 === -0 // true
(3) Zusammengesetzter Typwert
Beim Vergleich von Daten zweier zusammengesetzter Typen (Objekte, Arrays, Funktionen) geht es nicht darum, zu vergleichen, ob ihre Werte gleich sind, sondern darum, ob sie auf dieselbe Adresse verweisen.
{
} === {
} // false
[] === [] // false
(function () {
} === function () {
}) // false
Der obige Code vergleicht jeweils zwei leere Objekte, zwei leere Arrays und zwei leere Funktionen, und die Ergebnisse sind nicht gleich. Der Grund dafür ist, dass bei zusammengesetzten Typwerten die strikte Gleichheitsoperation vergleicht, ob sie sich auf dieselbe Speicheradresse beziehen, während die Werte leerer Objekte, leerer Arrays und leerer Funktionen auf beiden Seiten des Operators alle in unterschiedlichen Speichern gespeichert werden Adressen. Das Ergebnis ist natürlich false
.
Zwei Variablen sind gleich, wenn sie sich auf dasselbe Objekt beziehen.
var v1 = {
};
var v2 = v1;
v1 === v2 // true
Beachten Sie, dass bei Vergleichen zwischen zwei Objekten der strikte Gleichheitsoperator Adressen vergleicht, während der Größer-als- oder Kleiner-als-Operator Werte vergleicht.
var obj1 = {
};
var obj2 = {
};
obj1 > obj2 // false
obj1 < obj2 // false
obj1 === obj2 // false
Von den drei oben genannten Vergleichen vergleichen die ersten beiden Werte und der letzte Adressen, sodass sie alle zurückgegeben werden false
.
(4) undefiniert und null
undefined
und sind null
sich selbst strikt gleich.
undefined === undefined // true
null === null // true
Da der Standardwert nach der Deklaration einer Variablen lautet undefined
, sind zwei Variablen, die nur deklariert, aber keinem Wert zugewiesen werden, gleich.
var v1;
var v2;
v1 === v2 // true
strikter Ungleichheitsoperator
Der strikte Gleichheitsoperator verfügt über einen entsprechenden „strengen Ungleichheitsoperator“ ( !==
), dessen Algorithmus darin besteht, zuerst das Ergebnis des strikten Gleichheitsoperators zu finden und dann den entgegengesetzten Wert zurückzugeben.
1 !== '1' // true
// 等同于
!(1 === '1')
Im obigen Code wird das Ausrufezeichen !
verwendet, um den entgegengesetzten Wert des folgenden Ausdrucks zu finden.
Gleichheitsoperator
Der Gleichheitsoperator funktioniert genau wie der strikte Gleichheitsoperator, wenn er zum Vergleichen von Daten desselben Typs verwendet wird.
1 == 1.0
// 等同于
1 === 1.0
Beim Vergleich von Daten unterschiedlichen Typs konvertiert der Gleichheitsoperator zunächst den Datentyp und vergleicht ihn dann mit dem strikten Gleichheitsoperator. Das Folgende ist in mehrere Situationen unterteilt, um die Regeln für den Vergleich verschiedener Wertetypen miteinander zu erörtern.
(1) Wert des primitiven Typs
Primitive Typwerte werden in numerische Werte umgewandelt und verglichen.
1 == true // true
// 等同于 1 === Number(true)
0 == false // true
// 等同于 0 === Number(false)
2 == true // false
// 等同于 2 === Number(true)
2 == false // false
// 等同于 2 === Number(false)
'true' == true // false
// 等同于 Number('true') === Number(true)
// 等同于 NaN === 1
'' == 0 // true
// 等同于 Number('') === 0
// 等同于 0 === 0
'' == false // true
// 等同于 Number('') === Number(false)
// 等同于 0 === 0
'1' == true // true
// 等同于 Number('1') === Number(true)
// 等同于 1 === 1
'\n 123 \t' == 123 // true
// 因为字符串转为数字时,省略前置和后置的空格
Der obige Code wandelt sowohl Zeichenfolgen als auch boolesche Werte in numerische Werte um und vergleicht sie anschließend.
(2) Vergleich von Objekten und primitiven Typwerten
Wenn ein Objekt (hier bezieht sich auf ein verallgemeinertes Objekt, einschließlich Arrays und Funktionen) mit einem Wert des Originaltyps verglichen wird, wird das Objekt in einen Wert des Originaltyps konvertiert und dann verglichen.
Rufen Sie insbesondere valueOf()
zuerst die Methode des Objekts auf. Wenn Sie den Wert des ursprünglichen Typs erhalten, vergleichen Sie ihn gemäß den Regeln im vorherigen Abschnitt miteinander. Wenn Sie das Objekt erhalten, rufen Sie die Methode erneut auf, um die Zeichenfolgenform zu toString()
erhalten , und dann vergleichen.
Unten finden Sie ein Beispiel für den Vergleich eines Arrays mit einem Wert eines primitiven Typs.
// 数组与数值的比较
[1] == 1 // true
// 数组与字符串的比较
[1] == '1' // true
[1, 2] == '1,2' // true
// 对象与布尔值的比较
[1] == true // true
[2] == true // false
Im obigen Beispiel ruft die JavaScript-Engine zuerst die Methode [1]
des Arrays für das Array auf valueOf()
. Da die Rückgabe immer noch ein Array ist, ruft sie dann toString()
die Methode des Arrays auf, um die Zeichenfolgenform abzurufen, und vergleicht sie dann entsprechend Regeln im vorherigen Abschnitt.
Hier ist ein direkteres Beispiel.
const obj = {
valueOf: function () {
console.log('执行 valueOf()');
return obj;
},
toString: function () {
console.log('执行 toString()');
return 'foo';
}
};
obj == 'foo'
// 执行 valueOf()
// 执行 toString()
// true
Im obigen Beispiel obj
handelt es sich um ein Objekt mit einem Benutzerdefiniert valueOf()
und toString()
einer Methode. Wenn dieses Objekt 'foo'
mit einer Zeichenfolge verglichen wird, werden die Methoden valueOf()
und toString()
nacheinander aufgerufen und schließlich zurückgegeben 'foo'
, sodass das Vergleichsergebnis lautet true
.
(3) undefiniert und null
undefined
und null
werden nur zurückgegeben, wenn sie mit sich selbst oder untereinander verglichen werden true
; beim Vergleich mit Werten anderer Typen ist das Ergebnis false
.
undefined == undefined // true
null == null // true
undefined == null // true
false == null // false
false == undefined // false
0 == null // false
0 == undefined // false
(4) Nachteile des Gleichheitsoperators
Die vom Gleichheitsoperator verborgene Typkonvertierung kann zu kontraintuitiven Ergebnissen führen.
0 == '' // true
0 == '0' // true
2 == true // false
2 == false // false
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
Die oben genannten Ausdrücke unterscheiden sich von der Intuition und es kann leicht zu Fehlern kommen. Daher wird empfohlen, den Gleichheitsoperator ( ==
) nicht zu verwenden und am besten nur den strikten Gleichheitsoperator ( ===
) zu verwenden.
Ungleichheitsoperator
Der Gleichheitsoperator verfügt über einen entsprechenden „Ungleichheitsoperator“ ( !=
). Sein Algorithmus besteht darin, zuerst das Ergebnis des Gleichheitsoperators zu finden und dann den entgegengesetzten Wert zurückzugeben.
1 != '1' // false
// 等同于
!(1 == '1')
3. Boolesche Operatoren (logische Operatoren)
Boolesche Operatoren werden zum Konvertieren von Ausdrücken in boolesche Werte verwendet. Insgesamt gibt es vier Operatoren.
- Negationsoperator:
!
- Und (Gewerkschafts-)Operator:
&&
- Oder Betreiber:
||
- Ternärer Operator:
?:
Negationsoperator (!)
Der Negationsoperator ist ein Ausrufezeichen, das verwendet wird, um einen booleschen Wert in sein Gegenteil umzuwandeln, z. B. true
wird zu false
, false
wird true
.
!true // false
!false // true
Nicht-boolesche Werte werden vom Negationsoperator in boolesche Werte umgewandelt. Es kann auf diese Weise gespeichert werden: Die folgenden sechs Werte sind invertiert true
, und alle anderen Werte sind false
.
undefined
null
false
0
NaN
- leere Zeichenfolge (
''
)
!undefined // true
!null // true
!0 // true
!NaN // true
!"" // true
!54 // false
!'hello' // false
![] // false
!{
} // false
Im obigen Code wird der Wert unabhängig von der Art nach der Invertierungsoperation zu einem booleschen Wert.
Wenn Sie zwei aufeinanderfolgende Invertierungsoperationen für einen Wert ausführen, entspricht dies der Konvertierung in den entsprechenden booleschen Wert, der den Boolean
gleichen Effekt wie eine Funktion hat. Dies ist eine häufig verwendete Methode zur Typkonvertierung.
!!x
// 等同于
Boolean(x)
Unabhängig von der x
Art des Werts im obigen Code wird er nach zwei Negationsoperationen zum Boolean
gleichen booleschen Wert wie das Funktionsergebnis. Zweimaliges Negieren ist also nur eine Abkürzung für die Umwandlung eines Werts in einen booleschen Wert.
Und Operator (&&)
Und der Operator ( &&
) wird oft verwendet, um mehrere Ausdrücke auszuwerten.
Seine Operationsregeln lauten: Wenn der boolesche Wert des ersten Operators ist true
, wird der Wert des zweiten Operators zurückgegeben (beachten Sie, dass es sich um einen Wert und nicht um einen booleschen Wert handelt); wenn der boolesche Wert des ersten Operators ist, false
dann wird direkt zurückgegeben Der Wert des ersten Operators, und der zweite Operator wird nicht mehr ausgewertet.
't' && '' // ""
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""
var x = 1;
(1 - 1) && ( x += 1) // 0
x // 1
Da im letzten Beispiel des obigen Codes der boolesche Wert des ersten Operators des UND-Operators lautet false
, wird sein Wert direkt zurückgegeben, 0
ohne den zweiten Operator auszuwerten, sodass x
sich der Wert der Variablen nicht ändert.
Dieser Mechanismus des Überspringens des zweiten Operators wird als „Kurzschluss“ bezeichnet. Einige Programmierer verwenden es gerne, um if
die Struktur zu ersetzen. Das Folgende ist beispielsweise ein Teil if
des Strukturcodes, der mit dem Operator und umgeschrieben werden kann.
if (i) {
doSomething();
}
// 等价于
i && doSomething();
Die beiden Arten, den obigen Code zu schreiben, sind gleichwertig, aber der Zweck der letzteren ist nicht leicht zu erkennen und das Debuggen ist nicht einfach. Es wird empfohlen, sie mit Vorsicht zu verwenden.
false
Und Operatoren können in Verbindung mit mehreren Operatoren verwendet werden. In diesem Fall wird der Wert des Ausdrucks zurückgegeben, dessen erster boolescher Wert zurückgegeben wird . Wenn alle Ausdrücke einen booleschen Wert haben true
, wird der Wert des letzten Ausdrucks zurückgegeben.
true && 'foo' && '' && 4 && 'foo' && true
// ''
1 && 2 && 3
// 3
Im obigen Code in Beispiel 1 false
ist der erste Ausdruck mit einem booleschen Wert der dritte Ausdruck, sodass eine leere Zeichenfolge erhalten wird. Im zweiten Beispiel haben alle Ausdrücke boolesche Werte true
, sodass der Wert des letzten Ausdrucks zurückgegeben wird 3
.
ODER-Operator (||)
Der OR-Operator ( ||
) wird auch bei der Auswertung mehrerer Ausdrücke verwendet. Seine Betriebsregeln lauten: Wenn der erste Operator einen booleschen Wert hat true
, wird der Wert des ersten Operators zurückgegeben und der zweite Operator nicht ausgewertet; wenn der erste Operator einen booleschen Wert hat false
, wird der Wert des zweiten Operators zurückgegeben.
't' || '' // "t"
't' || 'f' // "t"
'' || 'f' // "f"
'' || '' // ""
Auch für diesen Betreiber gelten die Kurzschlussregeln.
var x = 1;
true || (x = 2) // true
x // 1
Im obigen Code ist der erste Operator des or-Operators true
, also kehren Sie direkt zurück true
, ohne den zweiten Operator auszuführen. Daher x
hat sich der Wert von nicht geändert. Dieser Mechanismus zur Steuerung, ob der zweite Ausdruck nur über den Wert des ersten Ausdrucks ausgeführt werden soll, wird als „Abkürzung“ bezeichnet.
true
Der OR-Operator kann mehrfach verwendet werden und gibt den Wert des Ausdrucks zurück, dessen erster boolescher Wert ist . Wenn alle Ausdrücke wahr sind false
, wird der Wert des letzten Ausdrucks zurückgegeben.
false || 0 || '' || 4 || 'foo' || true
// 4
false || 0 || ''
// ''
Im obigen Code in Beispiel 1 ist der erste true
Ausdruck mit einem booleschen Wert der vierte Ausdruck, sodass der Wert 4 erhalten wird. In Beispiel 2 lauten die booleschen Werte aller Ausdrücke false
, sodass der Wert des letzten Ausdrucks zurückgegeben wird.
Der OR-Operator wird häufig verwendet, um einen Standardwert für eine Variable festzulegen.
function saveText(text) {
text = text || '';
// ...
}
// 或者写成
saveText(this.text || '')
Der obige Code gibt an, dass der Parameter standardmäßig auf eine leere Zeichenfolge gesetzt ist, wenn beim Aufruf der Funktion kein Parameter angegeben wird.
Ternärer bedingter Operator (?:)
Der ternäre Bedingungsoperator besteht aus einem Fragezeichen (?) und einem Doppelpunkt (:), um drei Ausdrücke zu trennen. Es ist der einzige Operator in der JavaScript-Sprache, der drei Operatoren erfordert. true
Gibt den Wert des zweiten Ausdrucks zurück, wenn der erste Ausdruck ein boolescher Wert ist , andernfalls wird der Wert des dritten Ausdrucks zurückgegeben.
't' ? 'hello' : 'world' // "hello"
0 ? 'hello' : 'world' // "world"
t
Die booleschen Werte der Summen im obigen Code 0
lauten jeweils true
sum false
, sodass die Werte des zweiten und dritten Ausdrucks jeweils zurückgegeben werden.
Im Allgemeinen if...else
haben ternäre bedingte Ausdrücke die gleiche Ausdruckswirkung wie Sätze, und was der erstere ausdrücken kann, kann der letztere auch ausdrücken. Es gibt jedoch einen großen Unterschied zwischen den beiden: if...else
Es handelt sich um eine Anweisung ohne Rückgabewert; der ternäre bedingte Ausdruck ist ein Ausdruck und hat einen Rückgabewert. Wenn daher ein Rückgabewert erforderlich ist, können nur ternäre bedingte Ausdrücke verwendet werden, nicht jedoch if..else
.
console.log(true ? 'T' : 'F');
Im obigen Code console.log
muss der Parameter der Methode ein Ausdruck sein. In diesem Fall können nur ternäre bedingte Ausdrücke verwendet werden. Wenn Sie eine Anweisung verwenden möchten if...else
, müssen Sie den gesamten Codewortlaut ändern.
4. Bitoperatoren
Bitweise Operatoren konvertieren Operanden in binäre 32 -Bit-Ganzzahlen und führen dann Operationen für jedes Bit aus. Zum Beispiel:
Die 32 Bits von 5 sind:
00000000000000000000000000000101
Die 32 Bits von 100 sind:
00000000000000000000000001100100
Die 32 Bits von 15 sind:
00000000000000000000000000001111
Bitweise NICHT
Der bitweise NOT-Operator ~
wandelt die Zahl in eine binäre 32-Bit-Ganzzahl um und invertiert dann jedes Bit. Alle Einsen werden zu Nullen, alle Nullen werden zu Einsen
Zum Beispiel:
Die 32 Bits von 5 sind:
00000000000000000000000000000101
32 Bits von ~5 sind:
11111111111111111111111111111010
Der konvertierte Wert ist -6
Bitweises NICHT negiert im Wesentlichen die Operanden und subtrahiert 1.
bitweises UND
Der bitweise ODER-Operator &
wandelt zwei Zahlen in eine binäre 32-Bit-Ganzzahl um und führt eine bitweise UND-Operation für jedes Bit der beiden Zahlen durch. Die Regeln für bitweises UND lauten wie folgt:
erste Nummer | zweite Nummer | Ergebnis |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
Konkrete Beispiele:
console.log(12 & 10); // 8
Die 32-Bit-Binärdarstellung von 12 lautet: 1100.
Die 32-Bit-Binärdarstellung von 10 lautet: 1010
Das Ergebnis der bitweisen UND-Verknüpfung ist: 1000
bitweise oder
Der bitweise ODER-Operator |
wandelt zwei Zahlen in eine binäre 32-Bit-Ganzzahl um und führt eine bitweise ODER-Operation für jedes Bit der beiden Zahlen durch. Die Regeln für bitweises ODER lauten wie folgt:
erste Nummer | zweite Nummer | Ergebnis |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
Konkrete Beispiele:
console.log(12 | 10); // 14
Die 32-Bit-Binärdarstellung von 12 lautet: 1100.
Die 32-Bit-Binärdarstellung von 10 lautet: 1010
Das Ergebnis der bitweisen ODER-Verknüpfung ist: 1110
bitweises XOR
Der bitweise ODER-Operator ^
wandelt zwei Zahlen in binäre 32-Bit-Ganzzahlen um und führt für jedes Bit der beiden Zahlen eine bitweise XOR-Operation durch. Die Betriebsregel lautet: Wenn die beiden Bits unterschiedlich sind, wird 1 zurückgegeben, und wenn die beiden Bits gleich sind, wird 0 zurückgegeben, wie in der folgenden Tabelle gezeigt:
erste Nummer | zweite Nummer | Ergebnis |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
Konkrete Beispiele:
console.log(12 ^ 10); // 6
Die 32-Bit-Binärdarstellung von 12 lautet: 1100.
Die 32-Bit-Binärdarstellung von 10 lautet: 1010
Das Ergebnis der bitweisen XOR-Verknüpfung ist: 0110
Wenn bitweises XOR ein nicht ganzzahliger Wert ist und nur einer der beiden Operanden wahr ist, wird 1 zurückgegeben. Wenn beide Operanden wahr oder beide falsch sind, wird 0 zurückgegeben. Das Beispiel sieht wie folgt aus:
console.log(true ^ "Hello"); // 1
console.log(false ^ "Hello"); // 0
console.log(true ^ true); // 0
console.log("Hello" ^ "Hello"); // 0
console.log(false ^ false); // 0
console.log(true ^ false); // 1
Beachten Sie, dass „Hallo hier“ in NaN konvertiert wird
bitweise Verschiebung
Die bitweisen Verschiebungsoperatoren <<
und >>
verschieben alle Bits um einen angegebenen Betrag nach links oder rechts, wodurch eine Zahl effektiv mit einer angegebenen Potenz von 2 multipliziert oder dividiert wird.
<<
: Mit 2 mit der angegebenen Potenz multiplizieren
console.log(2<<2); // 8
2 mal 2 hoch 2 erhöht
00000010 umgewandelt in 00001000
>>
: Durch 2 mit der angegebenen Potenz dividieren
console.log(16>>1); // 8
16 dividiert durch 2 hoch 1
00010000 wird in 00001000 umgewandelt
5. Andere Betreiber
Void- Operator
Die Funktion des void- Operators besteht darin, einen Ausdruck auszuführen und dann keinen Wert oder undefiniert zurückzugeben .
void 0 // undefined
void(0) // undefined
Die oben genannten zwei Möglichkeiten, den Void- Operator zu schreiben, sind beide korrekt. Es empfiehlt sich die letztgenannte Form, also immer Klammern zu verwenden.
Da der Void- Operator eine hohe Priorität hat, kann es leicht zu falschen Ergebnissen kommen, wenn keine Klammern verwendet werden.
Beispielsweise entspricht „void 4 + 7“ tatsächlich „(void 4) + 7“ .
Unten finden Sie ein Beispiel für einen Void- Operator.
var x = 3;
void (x = 5) //undefined
x // 5
Der Hauptzweck dieses Operators ist das Lesezeichen-Tool des Browsers ( Bookmarklet ) und das Einfügen von Codes in Hyperlinks, um Webseitensprünge zu verhindern.
Bitte schauen Sie sich den Code unten an.
<script>
function f() {
console.log('Hello World');
}
</script>
<a href="http://example.com" onclick="f(); return false;">点击</a>
Im obigen Code wird nach dem Klicken auf den Link zuerst der Code von onclick ausgeführt . Da onclick false zurückgibt , springt der Browser nicht zu example.com .
Der Void- Operator kann die obige Schreibmethode ersetzen.
<a href="javascript: void(f())">文字</a>
Hier ist ein realistischeres Beispiel, bei dem der Benutzer auf den Link klickt, um das Formular abzuschicken, aber keine Seitenumleitung erfolgt.
<a href="javascript: void(document.form.submit())">
提交
</a>
Komma-Operator
Der Kommaoperator wird verwendet, um zwei Ausdrücke auszuwerten und den Wert des letzteren Ausdrucks zurückzugeben.
'a', 'b' // "b"
var x = 0;
var y = (x++, 10);
x // 1
y // 10
Im obigen Code gibt der Kommaoperator den Wert des letztgenannten Ausdrucks zurück.
Eine Verwendung des Kommaoperators besteht darin, Hilfsoperationen auszuführen, bevor ein Wert zurückgegeben wird.
var value = (console.log('Hi!'), true);
// Hi!
value // true
Im obigen Code wird zuerst die Operation vor dem Komma ausgeführt und dann der Wert nach dem Komma zurückgegeben.
6. Reihenfolge der Operationen
Priorität
Die Priorität ( Operator Precedence ) verschiedener Operatoren in JavaScript ist unterschiedlich. Operatoren mit höherer Priorität werden zuerst ausgeführt, Operatoren mit niedrigerer Priorität werden später ausgeführt.
4 + 5 * 6 // 34
Im obigen Code hat der Multiplikationsoperator ( * ) eine höhere Priorität als der Additionsoperator ( + ), daher wird zuerst die Multiplikation und dann die Addition durchgeführt, was dem Folgenden entspricht.
4 + (5 * 6) // 34
Wenn mehrere Operatoren miteinander vermischt werden, führt dies oft zu verwirrendem Code.
var x = 1;
var arr = [];
var y = arr.length <= 0 || arr[0] === undefined ? x : arr[0];
Im obigen Code ist der Wert der Variablen y schwer zu erkennen, da dieser Ausdruck fünf Operatoren umfasst. Es ist nicht leicht, sich zu merken, welcher die höchste Priorität hat.
Gemäß der Sprachspezifikation ist die Rangfolge dieser fünf Operatoren von hoch nach niedrig: kleiner oder gleich ( <= ), strikte Gleichheit ( === ) oder ( || ), ternär ( ?: ), Gleichheitszeichen ( = ). Daher ist die tatsächliche Reihenfolge der Operationen für den obigen Ausdruck wie folgt.
var y = ((arr.length <= 0) || (arr[0] === undefined)) ? x : arr[0];
Es ist schwierig und unnötig, sich die Priorität aller Operatoren zu merken.
Die Funktion von Klammern
Klammern können verwendet werden, um die Priorität einer Operation zu erhöhen, da ihre Priorität die höchste ist, d. h. der Ausdruck in Klammern wird zuerst ausgewertet.
(4 + 5) * 6 // 54
Im obigen Code wird aufgrund der Verwendung von Klammern die Addition vor der Multiplikation durchgeführt.
Die Prioritätsstufen der Operatoren sind sehr kompliziert und unterliegen strengen Regeln. Daher wird empfohlen, immer Klammern zu verwenden, um sicherzustellen, dass die Reihenfolge der Operationen klar und lesbar ist, was für die Codepflege und das Debuggen von entscheidender Bedeutung ist.
Klammern sind übrigens keine Operatoren, sondern ein Syntaxkonstrukt. Es hat zwei Verwendungszwecke: Zum einen wird der Ausdruck in Klammern gesetzt, um die Priorität der Operation zu erhöhen, und zum anderen wird der Funktion gefolgt, um die Funktion aufzurufen.
Beachten Sie, dass Klammern, da sie keine Operatoren sind, keine Auswirkung auf die Auswertung haben und nur die Priorität der Operation ändern.
var x = 1;
(x) = 2;
Wenn in der zweiten Zeile des obigen Codes die Klammern einen Bewertungseffekt haben, wird daraus 1 = 2 , was zu einem Fehler führt. Allerdings funktioniert der obige Code, der überprüft, ob die Klammern nur die Priorität und nicht die Auswertung ändern.
Dies bedeutet auch, dass der gesamte Ausdruck keine Wirkung hat, wenn er in Klammern eingeschlossen ist.
(expression)
// 等同于
expression
Wenn Sie eine Funktion in Klammern setzen, wird die Funktion selbst zurückgegeben. Wenn die Klammern unmittelbar auf die Funktion folgen, bedeutet dies, dass die Funktion aufgerufen wird.
function f() {
return 1;
}
(f) // function f(){return 1;}
f() // 1
Im obigen Code gibt die in Klammern gesetzte Funktion die Funktion selbst zurück, und die auf die Funktion folgenden Klammern rufen die Funktion auf.
Es können nur Ausdrücke in Klammern gesetzt werden. Wenn eine Anweisung in Klammern steht, wird ein Fehler gemeldet.
(var a = 1)
// SyntaxError: Unexpected token var
Linksverknüpfung und Rechtsverknüpfung
Bei Operatoren mit derselben Prioritätsebene tritt bei gleichzeitigem Auftreten ein Problem mit der Berechnungsreihenfolge auf.
a OP b OP c
Im obigen Code steht OP für den Operator. Es kann auf zwei Arten interpretiert werden.
// 方式一
(a OP b) OP c
// 方式二
a OP (b OP c)
Die mit den beiden oben genannten Methoden erzielten Berechnungsergebnisse sind häufig unterschiedlich.
Die erste Möglichkeit besteht darin, die beiden Operanden auf der linken Seite miteinander zu kombinieren. Der Operator, der diese Interpretationsmethode verwendet, wird als „Links-nach- rechts-Assoziativitätsoperator “ bezeichnet .
Die zweite Möglichkeit besteht darin, die beiden Operanden auf der rechten Seite zu kombinieren. Ein solcher Operator wird als „Rechts-nach-Links-Assoziativität“-Operator ( Rechts-nach-Links-Assoziativität ) bezeichnet.
Die meisten Operatoren in der JavaScript- Sprache sind „linksassoziativ“, siehe das Beispiel des Additionsoperators unten.
x + y + z
// 引擎解释如下
(x + y) + z
Im obigen Code werden x und y kombiniert und ihre Budgetergebnisse werden dann mit z berechnet .
Eine Handvoll Operatoren sind „rechtsassoziativ“, darunter vor allem der Zuweisungsoperator ( = ) und der ternäre Bedingungsoperator ( ?: ).
w = x = y = z;
q = a ? b : c ? d : e ? f : g;
Der obige Code wird wie folgt erklärt.
w = (x = (y = z));
q = a ? b : (c ? d : (e ? f : g));
In den beiden obigen Codezeilen werden die Operanden auf der rechten Seite kombiniert.
Auch der Exponentenoperator (**) ist rechtsassoziativ.
2 ** 3 ** 2
// 相当于 2 ** (3 ** 2)
// 512
Antworten auf echte Fragen
- Unter welchen Umständen wird im folgenden Code die Ausgabeanweisung ausgeführt und 1 ausgegeben ?
var a = ?;
if(a == 1 && a == 2 && a == 3){
console.log(1);
}
Referenzantwort:
Methode 1: Verwenden Sie die Methode toString()
var a = { i: 1, toString() { return a.i++; } } if (a == 1 && a == 2 && a == 3) { console.log('1'); }
Methode 2: Verwenden Sie die Methode valueOf()
var a = { i: 1, valueOf() { return a.i++ } } if (a == 1 && a == 2 && a == 3) { console.log('1'); }
- EOF -