Warum ist ",,," == Array (4) in Javascript?

119

Starten Sie Ihren Interpreter / Ihre Konsole und versuchen Sie den Vergleich

> ",,," == Array(4)
True

Warum? Zuerst dachte ich vielleicht, da man sich ",,," als ein Array von vier Zeichen mit einem '\ 0'-terminierenden Slice vorstellen könnte, könnte das der Grund sein, aber

> "..." == Array(4)

Gibt "False" zurück. Warum also? Ich weiß, dass es ein eigenwilliges Stück Ente ist, das in Javascript tippt, aber nur neugierig, was dieses Verhalten unterstreicht. Dies ergab sich übrigens aus Zed Shaws ausgezeichneter Präsentation hier .

ZenLikeThat
quelle
14
Nur wenige Sprachen außer C verwenden eine Nullterminierung, die für den Programmierer sichtbar ist.
Joey
7
Wenn ich fragen darf, was hat zu dieser Entdeckung geführt?
SomeKittens
1
@SomeKittens Zed Shaw erwähnt dies ausdrücklich in dem Video, auf das ich in meiner Frage verlinkt habe (als Kritik an Javascript). Prost!
ZenLikeThat
5
@SomeKittens Dies wird auch in dem (ziemlich bekannten) "Wat" -Gespräch erwähnt, das einige Macken in Ruby und JavaScript zeigt. Destillallsoftware.com/talks/wat
Cronco
5
Dies ist einer von vielen guten Gründen, immer ===statt zu verwenden ==.
wprl

Antworten:

178

Weil der rechte Operand in eine Zeichenfolge konvertiert wird und die Zeichenfolgendarstellung von Array(4)lautet ,,,:

> Array(4).toString()
  ",,,"

Wenn Sie die Array-Konstruktorfunktion verwenden und eine Zahl übergeben, wird die Länge des Arrays auf diese Zahl festgelegt. Sie können also sagen, dass Sie vier leere Indizes haben (wie [,,,]), und die Standard-Zeichenfolgendarstellung von Arrays ist eine durch Kommas getrennte Liste ihrer Elemente:

> ['a','b','c'].toString()
  "a,b,c"

Wie der Vergleich funktioniert, ist in Abschnitt 11.9.3 der Spezifikation beschrieben . Dort sehen Sie ( x == y):

8. Wenn Typ ( x ) entweder Zeichenfolge oder Zahl und Typ ( y ) Objekt ist,
geben Sie das Ergebnis des Vergleichs x == ToPrimitive ( y ) zurück.

(Arrays sind Objekte in JavaScript)

und wenn Sie der ToPrimitiveMethode folgen, werden Sie schließlich feststellen, dass sie aufgerufen wird toString.

Felix Kling
quelle
2
Okay, jetzt macht das alles Sinn für mich. Vielen Dank.
ZenLikeThat
6
Dies liegt wiederum daran, dass Arrays so stringiert werden, als würden sie verwendet Array.join(",").
Abenddämmerung -inaktiv-
Sie müssen blutig geduldig sein, um in Javascript zu programmieren
Matcheek
31

Intern geht es los

",,," == Array(4).toString()
Jason Kulatunga
quelle
31

Versuchen Sie es mit ===. Bei Verwendung ==in Javascript wird versucht, die Variablen umzuwandeln, was zu Problemen wie diesem führt. Die Konsole wandelt Array(4)in die Zeichenfolgendarstellung (dh Array(4).toString) um ",,,". Der Grund, warum die Kommas vorhanden sind, besteht darin, dass die .toString()Funktion sie zu separaten Elementen in einem Array hinzufügt.

Siehe den folgenden Ausschnitt:

document.write( Array(4).toString() );

SomeKittens
quelle
18

Dies liegt daran, dass Array(4)ein Array mit 4 leeren Werten initialisiert und ==implizit konvertiert wird.

 ",,," == Array(4)

 ",,," == Array(4).toString()

 ",,," == ["", "", "", ""] // note 3 commas for 4 values

 ",,," == ["", "", "", ""].toString()

Sind alle ähnlich.

==führt implizite Typkonvertierungen durch, bevor die Werte verglichen werden, was zu unvorhersehbaren Ergebnissen führen kann. Verwenden Sie ===diese Option , um den Typ und den Wert zu überprüfen.

Keith
quelle
5

Durch Vergleichen eines Arrays mit einem String wird das Array vor dem Vergleich zu einem String gezwungen. Wenn Sie ein leeres Array mit 4 Elementen zu einer Zeichenfolge zwingen, erhalten Sie genau diese Zeichenfolge.

Russell Borogove
quelle
4

Ich dachte zuerst, es sei etwas mit dem "Prototyp" ... aber nach einer kleinen Untersuchung kam ich zu einem traurigen Ergebnis ...

Anscheinend ist es eine interne und dunkelere Sache mit wenig Logik ...

Probier's einfach

Array(4)==Array(4)

und auch kein Zwang auf Typen ...

Array(4)===Array(4)

und du wirst FALSCH bekommen

Sie wissen , dass null==null, null===nullund auch undefined==undefinedund undefined===undefinedgibt TRUE zurück ... so ... es ist ein bisschen verschleiern ...

Array(4)==[,,,] sollte auch wahr sein

ZEE
quelle
ZEE, Array (4) == [,,,] wird nicht wahr sein. Wenn wir ein Objekt mit einem Grundelement vergleichen, wird das Objekt in ein Grundelement konvertiert. Aus diesem Grund wird toString () aufgerufen.
Devsathish
Array (x) sollte die Adresse des Konstruktors sein ... in einem System (egal welche Art von System) sollte <identity_X> === <identity_X> immer wahr sein!
ZEE