2013-09-01 9 views
47

Ich versuche, wörtliche Funktionen aufzurufen, aber ich bekomme seltsames Verhalten. Geben Sie diesen Code ein, der true zurückgibt.Calling Member-Funktion der Nummer Literal

23 === (23) 

Wenn ich schreibe, versuchen Sie Folgendes.

(23).toFixed(2) 

ich das erwartete Ergebnis _23.00_ aber wenn ich 23.toFixed(2) versuchen bekomme ich diesen Fehler.

SyntaxError: Unexpected token ILLEGAL

Wie bewertet JavaScript Ausdrücke, die das nicht verstehen und warum bekomme ich diesen Fehler?

Antwort

58

Die Antworten von Greg Hewgill und icktoofay sind in jeder Hinsicht korrekt, aber ich möchte etwas abstrahieren: Mal sehen, was wirklich nach der Javascript-Spezifikation passiert.

Section 7.8.3 der Spezifikation definiert numerische Literale. Wir können die folgenden sehen:

DecimalLiteral :: 
    DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt) 
    . DecimalDigits ExponentPart(opt) 
    DecimalIntegerLiteral ExponentPart(opt) 

DecimalIntegerLiteral :: 
    0 
    NonZeroDigit DecimalDigits(opt) 

A DecimalLiteral, eine Zahl, ist ein Bündel von Dezimalstellen, möglicherweise gefolgt von einem Punkt, der möglicherweise durch andere Ziffern gefolgt wird (die alle durch einen Exponenten verfolgt werden kann, e12 zum Beispiel). Mit anderen Worten, 42. ist legal und entspricht 42 und 3e2 entspricht 300.

Beachten Sie, wenn wir einen Punkt haben, erwarten wir entweder, dass ihm weitere Ziffern/Exponenten folgen oder dass nichts folgt. Jedoch, und das ist der wichtige Teil, der Punkt ist Teil der Nummer. Denken Sie daran, während wir uns bewegen, um zu sehen, wie der Punktoperator obj.prop behandelt wird.

Section 11.2.1, Property Accessors beschreibt den Punkt und Klammer-Notation für Mitglied Zugang:

MemberExpression . IdentifierName 

CallExpression für Funktionsaufrufe ist, die wir nicht interessieren. Beachten Sie, wie wir eine MemberExpression erwarten (die eine DecimalLiteral sein kann - aber nehmen Sie mein Wort dafür nicht, schauen Sie und sehen Sie, ob ich Recht habe).

Sehen Sie diesen kleinen Punkt? Es ist logisch, nach vorne zu springen und zu sagen: "Nun, hier ist ein Punkt im Schema ... und es gibt einen Punkt in 4.foo ... also, warum gibt es einen Fehler?" Leider habe ich meinen hypothetischen Freund, den ich für diese Sätze verwende, vergessen, wie die DecimalLiteral aussieht! Lassen Sie uns über zwei Beispiele gehen und sehen, was passiert.

42.foo 
^ 

Das Caret repräsentiert den Charakter, auf dem wir uns befinden. Bis jetzt sind wir innerhalb DecimalLiteral/DecimalIntegerLiteral/NonZeroDigit (das ist ziemlich ein Mundvoll). Lassen Sie sich auf das nächste Zeichen verschieben:

42.foo 
^ 

Noch Teil der Nummer, ein absolut gültigen DecimalDigit.

42.foo 
^

ok, so sind wir aus dem DecimalIntegerLiteral Teil. Hier ist das gleiche Diagramm auf dem Schema:

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt) 
        ^

So sind wir auf einem Punkt, der ein perfekt gültiger Teil einer Nummer ist. Jetzt verbrauchen wir es, als Teil der Nummer und bewegen auf:

42.foo 
^

f ist weder Teil DecimalDigits noch von ExponentPart sind wir jetzt von der Zahl aus. So was jetzt? Was ist das f? Es ist nicht Teil von irgendetwas. Vielleicht ist es ein Eigentum Accessor? Schauen wir uns die Regelung einen Blick:

MemberExpression . IdentifierName 
    ^

Wir sind auf jeden Fall auf MemberExpression, aber wir haben nicht einen Punkt haben, die es folgt -, dass Punkt bereits Teil der Zahl ist. Wir haben einen syntaktischen Fehler erreicht: Wir stoppen die Ausführung und werfen sie. Hoffentlich leben Sie nicht in einem Glashaus.

Hoffentlich verstehen Sie jetzt, warum 42..foo funktioniert. Sobald wir aus dem MemberExpression sind, dann stellen wir einen weiteren Punkt:

   42..foo 
       ^
MemberExpression . IdentifierName 
       ^

Gefolgt von einem völlig legal IdentifierName.

Natürlich gibt es mehrere andere Möglichkeiten, den Punkt von der Zahl zu trennen. Ein Weg, wie Sie gezeigt haben, besteht darin, das Literal in Klammern zu umgeben: (42).foo. Wenn wir das Ende der Klammern erreicht haben, sind wir außerhalb der MemberExpression, und auf den Punkt.Eine andere Möglichkeit besteht darin, ein Leerzeichen einzufügen: 42 .foo, da ein Leerzeichen nicht Teil der Nummer sein kann und es für den Parser neutral ist, sodass es keinen Fehler auslöst.

+1

Ausgezeichnete Antwort! –

35

Im Gegensatz zu Ruby (zum Beispiel) betrachtet der Javascript-Parser eine . folgende Ziffern als Teil der Zahl. So sieht der Parser die Token:

23.toFixed(2)

, die ein Syntaxfehler ist, weil das Wort toFixed sofort eine Gleitkommazahl folgenden ist nicht sinnvoll. Eine Sprache wie Ruby, die diese Syntax die folgenden Token sehen würde akzeptiert:

23.toFixed(2)

24

Betrachten:

5. 

Ist das der Floating-Point-Literal 5. oder eine ganze Zahl 5 gefolgt von einem Punkt? Du weißt es nicht; es ist mehrdeutig. JavaScript übernimmt die frühere Sichtweise. In der JavaScript-Ansicht haben Sie ein Fließkomma-Literal, gefolgt von einem Bezeichner (gefolgt von einer linken Klammer, einer Zahl und einer rechten Klammer).

Manche Menschen unter Verwendung von zwei Punkten um diese Arbeit:

23..toFixed(2) 

Da eine Floating-Point-Literal kann nur möglicherweise eine Dezimalstelle haben, der andere Punkt ist ein wörtlicher Punkt Token.

+1

'23.0.toFixed (2)' funktioniert auch – Ehtesham