Chiamare la funzione membro del numero letterale

Sto cercando di chiamare funzioni letterali, ma ho un comportamento strano.

Considera questo codice che restituisce true .

  23 === (23) 

Quando scrivo, prova quanto segue.

 (23).toFixed(2) 

Ottengo il risultato previsto _23.00_ ma quando provo 23.toFixed(2) ottengo questo errore.

SyntaxError: Token imprevisto ILLEGAL

In che modo JavaScript valuta le espressioni che non riescono a capirlo e perché ottengo questo errore?

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 secondo le specifiche javascript.

La sezione 7.8.3 della specifica definisce valori letterali numerici. Possiamo vedere quanto segue:

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

Un DecimalLiteral , un numero, è un gruppo di cifre decimali, eventualmente seguito da un punto, che è probabilmente seguito da altre cifre (tutte possono essere seguite da un esponente, ad esempio e12 ). In altre parole, 42. è legale e uguale a 42 e 3e2 è uguale a 300 .

Nota come se abbiamo un punto, o ci aspettiamo che sia seguito da più cifre / esponente, o che non venga seguito da nulla. Tuttavia, e questa è la parte importante, il punto è parte del numero . Ricorda questo mentre ci spostiamo per osservare come viene obj.prop l’operatore punto, obj.prop .

La sezione 11.2.1, Accessori proprietà descrive la notazione punto e parentesi per l’accesso membro:

 MemberExpression . IdentifierName 

CallExpression è per chiamate di funzione, che non ci interessa. Notate come ci aspettiamo un MemberExpression (che può essere un DecimalLiteral – ma non DecimalLiteral , guardate e vedete se ho ragione).

Vedi 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 riferimento rappresenta il personaggio su cui ci troviamo. Finora, siamo all’interno di DecimalLiteral / DecimalIntegerLiteral / NonZeroDigit (che è piuttosto un boccone). Passiamo al prossimo personaggio:

 42.foo ^ 

Ancora parte del numero, un DecimalDigit perfettamente valido.

 42.foo ^ 

ok, quindi siamo fuori dalla parte DecimalIntegerLiteral . Ecco lo stesso diagramma sullo schema:

 DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt) ^ 

Quindi siamo su un punto, che è una parte perfettamente valida di un numero. Ora lo consumiamo, come parte del numero , e passiamo a:

 42.foo ^ 

f non fa parte né di DecimalDigits né di ExponentPart , siamo fuori dal numero adesso. Così quello che ora? Cos’è quella f ? Non fa parte di niente. Forse è un accessorio di proprietà? Diamo un’occhiata allo schema:

 MemberExpression . IdentifierName ^ 

Siamo decisamente su MemberExpression , ma non abbiamo un punto che lo segue: quel 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.

Spero che ora capiate perché 42..foo funziona. Una volta usciti da MemberExpression , affrontiamo un altro punto:

  42..foo ^ MemberExpression . IdentifierName ^ 

Seguito da un IdentifierName perfettamente legale.

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 da MemberExpression e in 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.

A differenza di Ruby (ad esempio), il parser Javascript considera a . seguenti cifre per far parte del numero. Quindi il parser vede i token:

23. toFixed ( 2 )

che è un errore di syntax, perché la parola toFixed segue immediatamente un numero in virgola mobile non ha senso. Una lingua come Ruby che accetta questa syntax vedrebbe i seguenti token:

23 . toFixed ( 2 )

Prendere in considerazione:

 5. 

È il valore letterale a virgola mobile o un numero intero 5 seguito da un punto? Non lo sai; è ambiguo. JavaScript prende la precedente vista. Nella vista di JavaScript, hai un letterale a virgola mobile seguito da un identificatore (seguito da parentesi sinistra, numero e parentesi destra).

Alcune persone aggirano questo problema usando due punti:

 23..toFixed(2) 

Poiché un letterale a virgola mobile può avere solo un punto decimale, l’altro punto è un token punto letterale.