Le risposte di Greg Hewgill e icktoofay sono corrette in tutti i modi, tuttavia, mi piacerebbe scendere un po ', astrazione-saggio: vediamo cosa sta realmente accadendo in base alle specifiche javascript.
Section 7.8.3 della specifica definisce valori letterali numerici. Possiamo vedere:
DecimalLiteral ::
DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
. DecimalDigits ExponentPart(opt)
DecimalIntegerLiteral ExponentPart(opt)
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits(opt)
A DecimalLiteral
, un numero, è un gruppo di cifre decimali, eventualmente seguita da un punto, che è seguita eventualmente da altre cifre (ognuno dei quali può essere seguita da un esponente, e12
per esempio). In altre parole, 42.
è legale e uguale a 42
e 3e2
equivale a 300
.
Nota come se abbiamo un punto, ci aspettiamo che sia seguito da più cifre/esponente, o che non venga seguito da nulla. Tuttavia, e questa è la parte importante, il punto fa parte del numero. Ricorda questo mentre ci spostiamo per osservare come viene gestito l'operatore punto, obj.prop
.
Section 11.2.1, Property Accessors descrive il punto e la notazione staffa per l'accesso utente:
MemberExpression . IdentifierName
CallExpression
è per chiamate di funzione, che non ci interessano. Notate come ci aspettiamo un MemberExpression
(che può essere un DecimalLiteral
- ma non credetemi, guardate e vedete se ho ragione).
Vedere quel puntino? È logico saltare in avanti e dire "beh, c'è un punto nello schema qui ... e c'è un punto in 4.foo
... quindi perché c'è un errore?" Purtroppo il mio ipotetico amico che uso per queste frasi, hai dimenticato come appare il DecimalLiteral
! Andiamo oltre due esempi e vediamo cosa succede.
42.foo
^
Il punto di inserimento rappresenta il personaggio su cui ci troviamo. Finora, siamo all'interno di DecimalLiteral/DecimalIntegerLiteral/NonZeroDigit
(che è un bel boccone). Passiamo al carattere successivo:
42.foo
^
ancora parte del numero, una perfettamente valido DecimalDigit
.
42.foo
^
ok, così siamo fuori della parte DecimalIntegerLiteral
. Ecco lo stesso schema sullo schema:
DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
^
Quindi siamo su un punto, che è una parte perfettamente valida di un numero. Ora noi consumiamo, come parte del numero, e andare avanti:
42.foo
^
f
è né parte di DecimalDigits
né ExponentPart
, siamo fuori del numero ora. Così quello che ora? Cos'è quello f
? Non fa parte di niente. Forse è un accessorio di proprietà? Diamo uno sguardo al programma:
MemberExpression . IdentifierName
^
Siamo decisamente sulla MemberExpression
, ma non abbiamo un punto che lo segue - che punto è già parte del numero. Abbiamo raggiunto un errore sintattico: interrompiamo l'esecuzione e la gettiamo. Spero che tu non viva in una casa di vetro.
Speriamo che ora comprenda perché lo 42..foo
funziona. Una volta che siamo fuori del MemberExpression
, ci troviamo di fronte un altro punto:
42..foo
^
MemberExpression . IdentifierName
^
Seguita da una perfettamente legale IdentifierName
.
Naturalmente, ci sono molti altri modi per separare il punto dal numero. Un modo, come hai mostrato, è racchiudere il letterale tra parentesi: (42).foo
. Quando abbiamo raggiunto la fine delle parentesi, siamo fuori dallo MemberExpression
e sul punto.Un altro modo è inserire uno spazio: 42 .foo
, poiché uno spazio non può far parte del numero ed è neutro per il parser, quindi non genera un errore.
Ottima risposta! –