Warum ist diese Zeile in Javascript gültig?
var a = 0[0];
Danach a
ist undefined
.
javascript
Michael M.
quelle
quelle
true[0]
oder""[0]
"0"
einesnew Number(0)
Objekts abgerufen.0[0]
einen Wert zurückzugeben0["toString"]
Das ist großartig, danke, dass du darauf hingewiesen hast .Antworten:
Wenn Sie dies tun
0[0]
, verwandelt der JS-Interpreter den ersten0
in einNumber
Objekt und versucht dann, auf die[0]
Eigenschaft dieses Objekts zuzugreifenundefined
.Es liegt kein Syntaxfehler vor, da die Eigenschaftszugriffssyntax
0[0]
in diesem Zusammenhang von der Sprachgrammatik zugelassen wird. Diese Struktur (unter Verwendung von Begriffen in der Javascript-Grammatik) istNumericLiteral[NumericLiteral]
.Der relevante Teil der Sprachgrammatik aus Abschnitt A.3 der ES5 ECMAScript-Spezifikation ist folgender:
So kann man dem Grammatiker durch diesen Fortschritt folgen:
Und ähnlich
Expression
kann es auch sein, wennNumericLiteral
wir der Grammatik folgen, sehen wir, dass dies erlaubt ist:0[0]
Dies bedeutet, dass dies ein zulässiger Teil der Grammatik und somit kein SyntaxError ist.Zur Laufzeit dürfen Sie dann eine Eigenschaft lesen, die nicht vorhanden ist (sie wird nur als gelesen
undefined
), solange die Quelle, aus der Sie lesen, entweder ein Objekt ist oder eine implizite Konvertierung in ein Objekt aufweist. Und ein numerisches Literal hat tatsächlich eine implizite Konvertierung in ein Objekt (ein Zahlenobjekt).Dies ist eine der oft unbekannten Funktionen von Javascript. Die Typen
Number
,Boolean
undString
in Javascript sind in der Regel intern als Primitive (nicht ausgewachsene Objekte) gespeichert. Hierbei handelt es sich um eine kompakte, unveränderliche Speicherdarstellung (wahrscheinlich auf diese Weise aus Gründen der Implementierungseffizienz). Javascript möchte jedoch, dass Sie diese Grundelemente wie Objekte mit Eigenschaften und Methoden behandeln können. Wenn Sie also versuchen, auf eine Eigenschaft oder Methode zuzugreifen, die vom Grundelement nicht direkt unterstützt wird, zwingt Javascript das Grundelement vorübergehend in einen geeigneten Objekttyp, wobei der Wert auf den Wert des Grundelements festgelegt wird.Wenn Sie eine objektähnliche Syntax für ein Grundelement wie verwenden
0[0]
, erkennt der Interpreter dies als Eigenschaftszugriff für ein Grundelement. Die Antwort darauf besteht darin, das erste0
numerische Grundelement zu einem vollständigenNumber
Objekt zu zwingen, auf das es dann auf die[0]
Eigenschaft zugreifen kann . In diesem speziellen Fall ist die[0]
Eigenschaft eines Number-Objektsundefined
der Grund, weshalb Sie diesen Wert erhalten0[0]
.Hier ist ein Artikel über die automatische Konvertierung eines Grundelements in ein Objekt zum Zwecke des Umgangs mit Eigenschaften:
Das geheime Leben von Javascript-Primitiven
Hier sind die relevanten Teile der ECMAScript 5.1-Spezifikation:
9.10 CheckObjectCoercible
Löst TypeError aus, wenn value
undefined
oder istnull
, andernfalls wird zurückgegebentrue
.11.2.1 Property Accessors
Ein operativer Teil für diese Frage ist Schritt 5 oben.
8.7.1 GetValue (V)
Hier wird beschrieben, wie beim Aufrufen des Werts als Eigenschaftsreferenz
ToObject(base)
die Objektversion eines beliebigen Grundelements abgerufen wird .9.9 ToObject
Diese beschreibt , wie
Boolean
,Number
undString
Primitiven sind an eine Objektform mit der umgewandelt [[PrimitiveValue]] internem Eigenschaftssatz entsprechend.Als interessanter Test, wenn der Code so war:
Es wäre immer noch keine Syntax zur Analysezeit werfen , da dies technisch rechtliche Syntax ist, aber es wäre eine Typeerror zur Laufzeit werfen , wenn Sie den Code ausführen , weil , wenn die oben Eigenschaftenaccessoren Logik auf den Wert angewandt wird
x
, wird es nennenCheckObjectCoercible(x)
oder rufen SieToObject(x)
die wird sowohl eine Typeerror aus , wennx
istnull
oderundefined
.quelle
0[1,2]
ist auch gültig, was bedeutet das? (Ich aktualisiere die Frage)null
oderundefined
völlig in Ordnung ist, auch wenn diese Eigenschaften nicht vorhanden sind.0[2]
1,2
, gibt aber 2 zurück.Wie die meisten Programmiersprachen verwendet JS eine Grammatik, um Ihren Code zu analysieren und in eine ausführbare Form zu konvertieren. Wenn die Grammatik keine Regel enthält, die auf einen bestimmten Codeabschnitt angewendet werden kann, wird ein SyntaxError ausgelöst. Andernfalls wird der Code als gültig angesehen, unabhängig davon, ob er sinnvoll ist oder nicht.
Die relevanten Teile der JS-Grammatik sind
Da
0[0]
es diesen Regeln entspricht, wird es als gültiger Ausdruck betrachtet. Ob es richtig ist (z. B. zur Laufzeit keinen Fehler auslöst), ist eine andere Geschichte, aber ja, das ist es. So bewertet JS Ausdrücke wiesomeLiteral[someExpression]
:someExpression
(was beliebig komplex sein kann)Number
, Strings =>String
usw.)get property
Operation für Ergebnis (2) mit dem Eigenschaftsnamen Ergebnis (1) auf.So
0[0]
wird interpretiert alsHier ist ein Beispiel für einen gültigen , aber falschen Ausdruck:
Es wird gut analysiert, aber zur Laufzeit schlägt der Interpreter in Schritt 2 fehl (da er
null
nicht in ein Objekt konvertiert werden kann) und gibt einen Laufzeitfehler aus.quelle
var x = null; var a = x[0];
generiert keinen Syntaxfehler, löst aber zur Laufzeit einen TypeError aus.0[0]
einen Wert anstelle von undefiniert zurückzugebenEs gibt Situationen, in denen Sie eine Zahl in Javascript gültig abonnieren können:
Obwohl nicht sofort ersichtlich ist, warum Sie dies tun möchten, entspricht das Abonnieren in Javascript der Verwendung der gepunkteten Notation (obwohl die Punktnotation Sie auf die Verwendung von Bezeichnern als Schlüssel beschränkt).
quelle
(0).toString
(ohne die Funktion aufzurufen). Es ist eine Eigenschaft vom Typ Nummer.0
ist Eigenschaft zugegriffen , und da es nicht existiert,undefined
ist mehr richtig als in jfriend00 erläutert.0[0]
die undefiniert zurückgibt . Es ist wahrscheinlich, dass es wird, aber es muss nicht der Fall seinIch möchte nur darauf hinweisen, dass diese gültige Syntax in keiner Weise nur für Javascript gilt. Die meisten Sprachen haben einen Laufzeitfehler oder einen Typfehler, aber das ist nicht dasselbe wie ein Syntaxfehler. Javascript gibt in vielen Situationen, in denen eine andere Sprache möglicherweise eine Ausnahme auslöst, undefiniert zurück, auch wenn ein Objekt abonniert wird, das keine Eigenschaft mit dem angegebenen Namen hat.
Die Syntax kennt den Typ eines Ausdrucks nicht (selbst einen einfachen Ausdruck wie ein numerisches Literal) und ermöglicht es Ihnen, einen beliebigen Operator auf einen beliebigen Ausdruck anzuwenden. Zum Beispiel der Versuch, einen Index in Javascript zu erstellen
undefined
oder zunull
verursachenTypeError
. Es ist kein Syntaxfehler - wenn dieser niemals ausgeführt wird (auf der falschen Seite einer if-Anweisung), verursacht er keine Probleme, während ein Syntaxfehler per Definition immer zur Kompilierungszeit abgefangen wird (eval, Function usw.) , alle zählen als kompiliert).quelle
Weil es eine gültige Syntax ist und sogar gültiger Code interpretiert werden muss. Sie können versuchen, auf jede Eigenschaft eines Objekts zuzugreifen (und in diesem Fall wird 0 in ein Number-Objekt umgewandelt), und es gibt Ihnen den Wert, falls vorhanden, andernfalls undefiniert. Der Versuch, auf eine Eigenschaft von undefined zuzugreifen, funktioniert jedoch nicht, sodass 0 [0] [0] zu einem Laufzeitfehler führen würde. Dies würde jedoch weiterhin als gültige Syntax klassifiziert. Es gibt einen Unterschied zwischen der gültigen Syntax und dem, was keine Laufzeit- / Kompilierungsfehler verursacht.
quelle
Die Syntax ist nicht nur gültig, das Ergebnis muss auch nicht
undefined
in den meisten, wenn nicht allen vernünftigen Fällen sein. JS ist eine der reinsten objektorientierten Sprachen. Die meisten sogenannten OO-Sprachen sind klassenorientiert, in dem Sinne, dass Sie die Form (die an die Klasse gebunden ist) des einmal erstellten Objekts nicht ändern können, sondern nur den Status des Objekts. In JS können Sie sowohl den Status als auch die Form des Objekts ändern, und dies tun Sie häufiger als Sie denken. Diese Fähigkeit führt zu einem ziemlich undurchsichtigen Code, wenn Sie ihn missbrauchen. Ziffern sind unveränderlich, sodass Sie das Objekt selbst nicht ändern können, weder den Status noch die Form, damit Sie dies tun könnenDies ist ein gültiger Zuweisungsausdruck, der 1 zurückgibt, aber eigentlich nichts
0
zuweist. Die Ziffer ist unveränderlich. Was an sich etwas seltsam ist. Sie können einen gültigen und korrekten (ausführbaren) Assingment-Ausdruck haben, der nichts (*) zuweist. Der Typ der Ziffer ist jedoch ein veränderbares Objekt, sodass Sie den Typ mutieren können, und die Änderungen werden die Prototypkette entlang kaskadieren.Natürlich ist es weit entfernt von der Kategorie der vernünftigen Verwendung, aber die Sprache ist angegeben, um dies zu ermöglichen, da in anderen Szenarien die Erweiterung der Objektfunktionen tatsächlich sehr sinnvoll ist. Auf diese Weise werden jQuery-Plugins in das jQuery-Objekt eingebunden, um ein Beispiel zu geben.
(*) Es weist tatsächlich den Wert 1 der Eigenschaft eines Objekts zu, es gibt jedoch keine Möglichkeit, auf dieses (vorübergehende) Objekt zu verweisen, und es wird daher beim nächsten GC-Durchlauf gesammelt
quelle
In JavaScript ist alles ein Objekt. Wenn der Interpreter es analysiert, behandelt er 0 als Objekt und versucht, 0 als Eigenschaft zurückzugeben. Das gleiche passiert, wenn Sie versuchen, auf das 0. Element von true oder "" (leere Zeichenfolge) zuzugreifen.
Selbst wenn Sie 0 [0] = 1 setzen, werden die Eigenschaft und ihr Wert im Speicher festgelegt, aber während Sie auf 0 zugreifen, wird sie als Zahl behandelt (Verwechseln Sie hier nicht die Behandlung als Objekt und Zahl.)
quelle