51 votes

L'appel de la fonction membre de nombre littéral

Je suis en train d'appeler littérale fonctions, mais j'obtiens un comportement bizarre.

Considérer ce code qui renvoie true.

   23 === (23)

Quand j'écris essayez les solutions suivantes.

(23).toFixed(2)

J'obtiens le résultat escompté _23.00_ mais quand j'essaie 23.toFixed(2) , j'obtiens cette erreur.

SyntaxError: Unexpected token ILLÉGAL

Comment JavaScript évaluer des expressions qui ne peuvent pas comprendre cela et pourquoi j'ai cette erreur?

62voto

Zirak Points 13656

Les réponses par Greg Hewgill et icktoofay sont exacts à tous les égards, cependant, j'aimerais obtenir un peu à la baisse, de l'abstraction-sage: nous allons voir ce qui se passe réellement selon le javascript de la spécification.

Section 7.8.3 de la spécification définit les littéraux numériques. Nous pouvons voir les suivants:

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

DecimalIntegerLiteral ::
    0 
    NonZeroDigit DecimalDigits(opt)

Un DecimalLiteral, un nombre, c'est un tas de chiffres après la virgule, suivi éventuellement par un point, qui est peut-être suivie par d'autres chiffres (qui peut être suivie par un exposant, e12 par exemple). En d'autres termes, 42. est juridique et l'égalité d' 42 et 3e2 est égal à 300.

Notez comment, si nous avons un point, soit nous attendons qu'il soit suivi par plus de chiffres/de l'exposant, ou être suivi par rien. Cependant, et c'est l'essentiel, le point est en partie du nombre. Rappelez-vous ce que nous allons regarder comment l'opérateur point, obj.prop, est traitée.

Section 11.2.1, les Accesseurs de Propriété décrit la dot et le support de la notation pour l'accès des membres:

MemberExpression . IdentifierName

CallExpression est pour les appels de fonction, dont nous ne nous soucions pas. Remarquez comment nous nous attendons à un MemberExpression (qui peut être un DecimalLiteral - mais ne prenez pas mon mot pour lui, de regarder et de voir si je suis à droite).

Vous voyez ce petit point? Il est donc logique de sauter en avant et dire: "eh bien, il y a un point dans le schéma ici...et il y a un point en 4.foo...alors pourquoi est-il une erreur?" Hélas mon hypothétique ami que j'ai utiliser pour ces phrases, vous avez oublié comment l' DecimalLiteral ressemble! Voici deux exemples et voir ce qui se passe.

42.foo
^

Le signe représente le caractère que nous sommes. Jusqu'à présent, nous sommes à l'intérieur d' DecimalLiteral / DecimalIntegerLiteral / NonZeroDigit (c'est tout à fait une bouchée). Nous allons passer au caractère suivant:

42.foo
 ^

Encore partie du nombre, parfaitement valide DecimalDigit.

42.foo
  ^

ok, donc nous sommes hors de l' DecimalIntegerLiteral partie. Voici le même schéma sur le schéma:

DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
                      ^

Nous sommes donc sur un point, ce qui est parfaitement valide de la part d'un certain nombre. Maintenant que nous consommons, en tant que partie du nombre, et de passer:

42.foo
   ^

f ne fait pas partie de l' DecimalDigits ni ExponentPart, nous sommes sortis du nombre maintenant. Alors...à quoi maintenant? Qu'est-ce que f? Il n'est pas partie de rien. C'est peut-être une propriété de l'accesseur? Jetons un coup d'oeil au schéma:

MemberExpression . IdentifierName
      ^

Nous sommes certainement sur MemberExpression, mais nous n'avons pas un point qui le suit - que la dot est déjà partie du nombre. Nous avons atteint une erreur de syntaxe: on arrête l'exécution et de la jeter. J'espère que vous ne vivez pas dans une maison de verre.

Espérons que maintenant vous comprenez pourquoi 42..foo travaux. Une fois que nous sommes hors de l' MemberExpression, nous sommes confrontés à un autre point:

              42..foo
                 ^
MemberExpression . IdentifierName
                 ^

Suivie par une parfaitement légale IdentifierName.

Bien sûr, il y en a plusieurs autres façons de séparer le point de le nombre. Une façon, comme vous l'a montré, c'est d'entourer la lettre entre parenthèses: (42).foo. Lorsque nous avons atteint les parenthèses à la fin, nous sommes hors de l' MemberExpression, et sur la dot. Une autre façon est d'insérer un espace: 42 .foo, depuis un espace ne peut pas faire partie du nombre, et il est neutre pour l'analyseur, afin de ne pas générer une erreur.

36voto

Greg Hewgill Points 356191

Contrairement à Ruby (par exemple), Le code Javascript de l'analyseur estime . chiffres suivants pour faire partie du nombre. Si l'analyseur voit les jetons:

23. toFixed ( 2 )

ce qui est une erreur de syntaxe, parce que le mot toFixed immédiatement à la suite d'un nombre à virgule flottante n'a pas de sens. Une langue comme le Rubis qui accepte cette syntaxe voir les marques suivantes:

23 . toFixed ( 2 )

23voto

icktoofay Points 60218

Considérer:

5.

C'est que la virgule flottante littérale 5. ou un entier 5 suivi par un point? Vous ne connaissez pas; c'est ambigu. JavaScript prend le premier point de vue. En JavaScript, vous avez un virgule flottante littérale suivie par un identificateur (suivi d'une parenthèse ouvrante, le nombre, et une parenthèse fermante).

Certaines personnes contourner cela en utilisant deux points:

23..toFixed(2)

Depuis un virgule flottante littérale ne peut éventuellement avoir un point décimal, l'autre point est un littéral point de jeton.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X