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.