Um Waynes Antwort zu ergänzen und zu erklären, warum sie ToPrimitive([])
zurückkehrt ""
, sollten zwei mögliche Arten von Antworten auf die Warum-Frage in Betracht gezogen werden. Die erste Art der Antwort lautet: "Weil die Spezifikation besagt, dass sich JavaScript so verhält." In der ES5-Spezifikation, Abschnitt 9.1 , der das Ergebnis von ToPrimitive als Standardwert für ein Objekt beschreibt:
Der Standardwert eines Objekts wird durch Aufrufen der internen Methode [[DefaultValue]] des Objekts abgerufen, wobei der optionale Hinweis PreferredType übergeben wird.
Abschnitt 8.12.8 beschreibt die [[DefaultValue]]
Methode. Diese Methode verwendet einen "Hinweis" als Argument, und der Hinweis kann entweder String oder Number sein. Um die Angelegenheit zu vereinfachen, indem auf einige Details verzichtet wird, gibt der Hinweis, wenn er String ist, [[DefaultValue]]
den Wert von zurück, toString()
falls vorhanden, und gibt einen primitiven Wert zurück, andernfalls den Wert von valueOf()
. Wenn der Hinweis Number ist, werden die Prioritäten von toString()
und valueOf()
umgekehrt, sodass valueOf()
zuerst aufgerufen und der Wert zurückgegeben wird, wenn es sich um ein Grundelement handelt. Also, ob [[DefaultValue]]
das Ergebnis von toString()
oder zurückgibtvalueOf()
für den angegebenen PreferredType für das Objekt zurückgegeben wird und ob diese Funktionen primitive Werte zurückgeben oder nicht.
Die Standardobjektmethode gibt valueOf()
nur das Objekt selbst zurück. Wenn eine Klasse die Standardmethode nicht überschreibt, wird valueOf()
nur das Objekt selbst zurückgegeben. Dies ist der Fall für Array
. [].valueOf()
gibt das Objekt []
selbst zurück. Da ein Array
Objekt kein Grundelement ist, ist der [[DefaultValue]]
Hinweis irrelevant: Der Rückgabewert für ein Array ist der Wert vontoString()
.
Um David Flanagans JavaScript zu zitieren : The Definitive Guide , das übrigens ein hervorragendes Buch ist, das der erste Ort sein sollte, an dem jeder Antworten auf diese Art von Fragen erhält:
Die Details dieser Konvertierung von Objekt in Nummer erklären, warum ein leeres Array in die Nummer 0 konvertiert wird und warum ein Array mit einem einzelnen Element auch in eine Nummer konvertiert werden kann. Arrays erben die Standardmethode valueOf (), die ein Objekt anstelle eines primitiven Werts zurückgibt. Daher hängt die Konvertierung von Array in Nummer von der Methode toString () ab. Leere Arrays werden in die leere Zeichenfolge konvertiert. Und die leere Zeichenfolge wird in die Zahl 0 konvertiert. Ein Array mit einem einzelnen Element wird in dieselbe Zeichenfolge konvertiert wie dieses eine Element. Wenn ein Array eine einzelne Nummer enthält, wird diese Nummer in eine Zeichenfolge und dann zurück in eine Nummer konvertiert.
Die zweite Art der Antwort auf die "Warum" -Frage, abgesehen von "Weil die Spezifikation sagt", gibt eine Erklärung dafür, warum das Verhalten aus der Designperspektive sinnvoll ist. Zu diesem Thema kann ich nur spekulieren. Wie würde man ein Array in eine Zahl umwandeln? Die einzig sinnvolle Möglichkeit, die ich mir vorstellen kann, wäre, ein leeres Array in 0 und jedes nicht leere Array in 1 zu konvertieren. Wie Waynes Antwort jedoch ergab, wird ein leeres Array für viele Arten von Vergleichen ohnehin in 0 konvertiert. Darüber hinaus fällt es schwer, sich einen sinnvollen primitiven Rückgabewert für Array.valueOf () vorzustellen. Man könnte also argumentieren, dass es nur sinnvoller ist Array.valueOf()
, der Standard zu sein und das Array selbst zurückzugebentoString()
zu dem von ToPrimitive verwendeten Ergebnis führt. Es ist nur sinnvoller, ein Array in eine Zeichenfolge anstatt in eine Zahl zu konvertieren.
Darüber hinaus ermöglicht diese Entwurfsentscheidung, wie aus dem Flanagan-Zitat hervorgeht, bestimmte Arten von vorteilhaften Verhaltensweisen. Zum Beispiel:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
Mit diesem Verhalten können Sie ein Einzelelementarray mit Zahlen vergleichen und das erwartete Ergebnis erhalten.