Warum ist [1,2,3] in Javascript nicht gleich?

9

Ich habe heute mit Arrays in Javascript herumgespielt und dieses kleine Juwel bemerkt:

%Vor%

Es kommt mir ziemlich seltsam vor, dass das Array nicht mit sich selbst übereinstimmt.

Aber dann bemerkte ich das, was noch seltsamer war:

%Vor%

?!?!?!? !!!?

Warum in der Welt ist [1, 2, 3] nicht == für sich selbst, aber ist == für die Zeichenkette?

Mir ist klar, dass == nicht gleich wie === ist. Trotzdem, welche Bosheit könnte Mr. Javas seltsame Dinge verursachen?

    
Peter Olson 06.09.2011, 03:30
quelle

6 Antworten

12

Ok, also zuerst müssen Sie verstehen, wie JavaScript Werte in Ihrem Programm behandelt. Alle von Ihnen erstellten Variablen werden lediglich Referenzen an einen Speicherort im Speicher sein, an dem das Objekt gespeichert ist. Daher, wenn Sie dies tun:

%Vor%

... es macht drei Dinge:

  1. Platzieren Sie ein Array ([1,2,3]) auf dem Heap
  2. Platzieren Sie ein weiteres Array ([1,2,3]) auf dem Heap (beachten Sie, dass es einen anderen Speicherort hat)
  3. Vergleichen Sie die beiden Referenzen. Sie verweisen auf verschiedene Objekte an verschiedenen Speicherorten, so dass sie als nicht gleich betrachtet werden.

Sie können auf etwas vernünftiges Verhalten prüfen, indem Sie diesen Code ausführen:

%Vor%

Nun zu Ihrer Frage zu der Zeichenfolge

Wenn Sie den Operator == verwenden, versucht er, die beiden Operanden in den gleichen Typ zu konvertieren (böses Verhalten ... ich weiß ...)

Wenn es dies tut, entscheidet es, beide in eine Zeichenkette zu konvertieren, bevor es den Vergleich durchführt (das Ergebnis ist also wirklich "1,2,3" === "1,2,3" , was zu true führt.

Ich kann Ihnen kein vollständiges Bild geben, da es nur wenige Menschen gibt, die jede Nuance des Wahnsinns verstehen, der JavaScript ist, aber hoffentlich wird dadurch etwas Nebel beseitigt.

    
riwalk 06.09.2011, 03:32
quelle
4

Für den ersten Teil erstellen Sie zwei verschiedene Objekte, da Arrays nur Objekte sind und da Sie zwei davon erstellt haben, sind beide eindeutig.

    
meder omuraliev 06.09.2011 03:32
quelle
3
  

== operator

     

[..] Wenn einer der beiden Operanden eine Zeichenfolge ist, wird der andere Operand möglichst in eine Zeichenfolge konvertiert. [..] Wenn beide Operanden Objekte sind, vergleicht JavaScript interne Referenzen, die gleich sind, wenn sich Operanden auf dasselbe Objekt im Speicher beziehen.

     

Ссылка

Das heißt, dass [1, 2, 3] in eine Zeichenkette umgewandelt wird, die gleich "1,2,3" ist. Ein Array-Objekt ist jedoch keinem anderen Array-Objekt gleich.

    
deceze 06.09.2011 03:35
quelle
2

Der erste Vergleich schlägt fehl, weil bei einem grundlegenden Vergleich zweier Objekte überprüft wird, ob es sich um das gleiche referenzierte Objekt handelt, und nicht, wenn die beiden Objekte die gleichen Werte haben. Wenn Sie zwei Arrays vergleichen möchten, müssen Sie die Werte durchlaufen.

%Vor%

Denken Sie daran, dass dies kein rekursiver Vergleich ist, so dass er nur für ein Array primitiver Werte funktioniert.

Der zweite Vergleich funktioniert, weil == versucht, die Typen der Argumente zu erzwingen, und wenn Sie ein Array in einen String konvertieren, ist das das Ergebnis.

%Vor%     
loganfsmyth 06.09.2011 03:39
quelle
1

Die beiden Array -Objekte sind verschieden und daher bei Verwendung des Vergleichs == nicht gleich. Um sie zu vergleichen, müssten Sie eine Schleife erstellen, wobei der Index in beiden identisch ist (und rekursiv, wenn die Elemente auch Array s oder Object s sind).

Der zweite Grund ist, dass Array implizit seinen toString() aufgerufen hat, der '1,2,3' zurückgegeben hat (try it).

Dies liegt daran, dass nach den Regeln eines Vergleichs von == (nicht streng) in ECMAScript der linke Operator zu einem String gezwungen wurde ( == führt eine Konvertierung durch).

    
alex 06.09.2011 03:34
quelle
1

Weil == nur dann erzwingt, wenn es ist, den gleichen Typ zu erhalten (z. B. nur, wenn die Typen der Operanden unterschiedlich sind). Wenn Sie

tun %Vor%

... kein Zwang ist erforderlich; beides sind Objekte. Sie sind nicht das selbe Objekt, also ist es false . Leute denken an == als den "erzwingenden" Gleichheitsoperator, und das ist es, aber der Schlüssel ist, dass es nur dann erzwingt, wenn es ist.

Aber tun

%Vor%

... beinhaltet Operanden von verschiedenen Typen: String und Objekt. So ist Zwang getan. In diesem Fall wird das Objekt wie in String(obj) zum String gezwungen, was sein Standardverhalten toString aufruft, was für Arrays .join() ist. join wird standardmäßig auf "," als Trennzeichen gesetzt, sodass die resultierende Zeichenfolge mit "1,2,3" übereinstimmt. (Sie finden die vollständige Logik, warum das Objekt gezwungen wird, in der Spezifikation zu stringeln. )

    
T.J. Crowder 04.10.2017 16:17
quelle

Tags und Links