Ein wenig bekanntes JS-Problem: [] == ![] ist wahr, aber {} == !{} ist falsch

Ein wenig bekanntes JS-Problem: [] == ![] ist wahr, aber {} == !{} ist falsch
konsole.log( [] == ![] ) // wahr
console.log( {} == !{} ) // falsch

Beim Vergleichen von Zeichenfolgen, Zahlen und Booleschen Werten auf Gleichheit ist das Problem relativ einfach. Beim Vergleichen von Objekten wird das Problem jedoch komplizierter. Die ursprünglichen Gleichheits- und Ungleichheitsoperatoren in ECMAScript konvertierten Objekte in ähnliche Typen, bevor der Vergleich durchgeführt wurde. Später stellten einige Leute die Sinnhaftigkeit dieser Umstellung in Frage. Schließlich besteht die Lösung von ECMAScript darin, zwei Operatorsätze bereitzustellen:

Gleichheit und Ungleichheit - erst umrechnen, dann vergleichen (==)
Kongruent und Nicht-kongruent - Vergleichen ohne Konvertierung (===)

Der Gleichheitsoperator in ECMAScript wird durch zwei Gleichheitszeichen (==) dargestellt. Wenn die beiden Operanden gleich sind, wird „true“ zurückgegeben. Dieser Operator konvertiert zuerst die Operanden (normalerweise erzwungene Konvertierung genannt) und vergleicht dann ihre Gleichheit.

Bei der Konvertierung verschiedener Datentypen, für Gleichheits- und Ungleichheitsoperatoren: Die folgenden grundlegenden Konvertierungsregeln finden Sie im Buch JS Elevation

① Wenn ein Operand ein Boolescher Wert ist, wird er vor dem Vergleich auf Gleichheit in einen numerischen Wert umgewandelt – „false“ wird in 0 und „true“ in 1 umgewandelt.

② Wenn ein Operand eine Zeichenfolge und der andere Operand eine Zahl ist, konvertieren Sie die Zeichenfolge in eine Zahl, bevor Sie auf Gleichheit vergleichen

③. Wenn ein Operand ein Objekt ist und der andere nicht, rufen Sie die valueOf()-Methode des Objekts auf und verwenden Sie den erhaltenen Wert des primitiven Typs zum Vergleichen gemäß den vorherigen Regeln.

Diese beiden Operatoren befolgen beim Durchführen von Vergleichen die folgenden Regeln.

①, null und undefiniert sind gleich

② Vor dem Vergleich auf Gleichheit können Null und Undefiniert nicht in einen anderen Wert konvertiert werden

③. Wenn ein Operand NaN ist, gibt der Gleichheitsoperator „false“ zurück, während der Ungleichheitsoperator „true“ zurückgibt. Wichtig: Auch wenn beide Operanden NaN sind, gibt der Gleichheitsoperator „Falsch“ zurück, da NaN per Regel nicht gleich NaN ist.

④. Wenn beide Operanden Objekte sind, vergleichen Sie, ob sie dasselbe Objekt sind. Wenn beide Operanden auf dasselbe Objekt zeigen, gibt der Gleichheitsoperator true zurück, andernfalls false.

Hier ein Exkurs: [] und {} sind beides Referenztypen, die im Heap-Speicher gespeichert sind, und im Stack-Speicher gibt es eine oder mehrere Adressen, die auf die Daten verweisen, die diesem Heap-Speicher entsprechen. Wenn Sie also den Operator == für Daten vom Referenztyp verwenden, wird die Adresse verglichen, nicht der tatsächliche Wert.

Lassen Sie uns nun diskutieren, warum das Ergebnis von [] == ! [] wahr ist

①. Entsprechend der Priorität des Bedieners, ! Die Priorität von ist größer als ==, also wird es zuerst ausgeführt![]

! Variablen können in den Booleschen Typ konvertiert werden. Die Negation von Null, undefiniert, NaN und leerem String ('') ist wahr, der Rest ist falsch.

Also! Das Ergebnis nach der []-Operation ist falsch

Das heißt, [] == ! [] ist gleichbedeutend mit [] == false

② Gemäß den oben genannten Regeln (wenn ein Operand ein Boolescher Wert ist, wird er vor dem Vergleichen der Gleichheit in einen numerischen Wert umgewandelt - false wird in 0 und true in 1 umgewandelt) müssen Sie false in 0 umwandeln

Das heißt, [] == ! [] ist gleichbedeutend mit [] == false, was gleichbedeutend mit [] == 0 ist.

③. Gemäß den oben genannten Regeln (wenn ein Operand ein Objekt ist und der andere Operand nicht, wird die valueOf()-Methode des Objekts aufgerufen und der erhaltene primitive Typwert wird gemäß den vorherigen Regeln verglichen. Wenn das Objekt keine valueOf()-Methode hat, wird toString() aufgerufen)

Für ein leeres Array: [].toString() -> '' (gibt einen leeren String zurück)

Das heißt, [] == 0 ist gleichbedeutend mit '' == 0

④ Gemäß den oben genannten Regeln (wenn ein Operand eine Zeichenfolge und der andere Operand eine Zahl ist, wird die Zeichenfolge vor dem Gleichheitsvergleich in eine Zahl umgewandelt).

Number('') -> gibt 0 zurück

Dies entspricht 0 == 0, was natürlich true zurückgibt.

Um es zusammenzufassen:

[] == ! [] -> [] == falsch -> [] == 0 -> '' == 0 -> 0 == 0 -> wahr

Das gleiche gilt für {} == !{}

Der Schlüssel ist {}.toString() -> NaN (gibt NaN zurück)

Gemäß den obigen Regeln (wenn ein Operand NaN ist, gibt der Gleichheitsoperator „false“ zurück)

Um es zusammenzufassen:

{} == ! {} -> {} == false -> {} == 0 -> NaN == 0 -> false

Dann glaube ich, dass jeder die folgenden beiden Fragen leicht beantworten kann.

console.log( [] == !{} ) // wahr
console.log( {} == ![] ) // falsch

Zusammenfassen

Damit ist dieser Artikel über das wenig bekannte JS-Problem abgeschlossen, dass [] == ![] als wahr ausgewertet wird, während {} == !{} als falsch ausgewertet wird. Weitere Informationen dazu, wie JS [] == ![] als wahr ausgewertet wird, finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

<<:  mysql5.7.22 Download-Prozessdiagramm

>>:  So löschen Sie Ordner, Dateien und Dekomprimierungsbefehle auf Linux-Servern

Artikel empfehlen

Der Implementierungsprozess der ECharts Multi-Chart-Verknüpfungsfunktion

Wenn viele Daten angezeigt werden müssen, ist die...

ElementUI implementiert kaskadierenden Selektor

In diesem Artikelbeispiel wird der spezifische Co...

Tutorial zur Verwendung des Multitail-Befehls unter Linux

MultiTail ist eine Software zum gleichzeitigen Üb...

Native JS-Canvas zum Erzielen einer einfachen Schlange

In diesem Artikel wird der spezifische Code von J...

So konfigurieren Sie die Linux-Firewall und öffnen die Ports 80 und 3306

Port 80 ist ebenfalls konfiguriert. Geben Sie zun...

Die Bilder in HTML werden direkt durch base64-kodierte Strings ersetzt

Kürzlich stieß ich auf eine Webseite, die zwar Bil...

Docker-Compose-Installation DB2-Datenbankbetrieb

Es ist mühsam, die db2-Datenbank direkt auf dem H...

Vorgehensweise bei der Installation einer virtuellen VMware Workstation-Maschine

Virtuelle Maschinen sind eine sehr praktische Tes...

Tutorial zur Installation von MYSQL5.7 aus dem OEL7.6-Quellcode

Laden Sie zunächst das Installationspaket von der...

innodb_flush_method-Wertmethode (Beispielerklärung)

Mehrere typische Werte von innodb_flush_method fs...