javascript - numeros - Llamando a la función miembro del número literal
mostrar numero mayor javascript (3)
Intento llamar funciones literales, pero tengo un comportamiento extraño.
Considere este código que devuelve true
.
23 === (23)
Cuando escribo, intente lo siguiente.
(23).toFixed(2)
Obtengo el resultado esperado _23.00_
pero cuando pruebo 23.toFixed(2)
este error.
SyntaxError: fichas inesperado ILEGAL
¿Cómo evalúa JavaScript las expresiones que no pueden entender esto y por qué obtengo este error?
A diferencia de Ruby (por ejemplo), el analizador de JavaScript considera a .
los siguientes dígitos para ser parte del número. Entonces el analizador ve los tokens:
23.
toFixed
(
2
)
que es un error de sintaxis, porque la palabra " toFixed
inmediatamente después de un número de coma flotante no tiene sentido. Un lenguaje como Ruby que acepte esta sintaxis verá los siguientes tokens:
23
.
toFixed
(
2
)
Considerar:
5.
¿Es ese el punto flotante literal 5.
o un número entero 5
seguido de un punto? Tu no sabes; es ambiguo JavaScript toma la vista anterior. En la vista de JavaScript, tiene un literal de coma flotante seguido de un identificador (seguido de un paréntesis izquierdo, un número y un paréntesis de la derecha).
Algunas personas trabajan alrededor de esto usando dos puntos:
23..toFixed(2)
Como un literal de punto flotante solo puede tener un punto decimal, el otro es un token de punto literal.
Las respuestas de Greg Hewgill y icktoofay son correctas en todos los sentidos, sin embargo, me gustaría profundizar un poco, en lo que icktoofay abstracción: veamos qué está sucediendo realmente de acuerdo con la especificación de JavaScript.
La sección 7.8.3 de la especificación define literales numéricos. Podemos ver lo siguiente:
DecimalLiteral ::
DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
. DecimalDigits ExponentPart(opt)
DecimalIntegerLiteral ExponentPart(opt)
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits(opt)
Un DecimalLiteral
, un número, es un grupo de dígitos decimales, posiblemente seguidos por un punto, que es posiblemente seguido por otros dígitos (todos los cuales pueden ser seguidos por un exponente, e12
, por ejemplo). En otras palabras, 42.
es legal e igual a 42
y 3e2
es igual a 300
.
Tenga en cuenta que si tenemos un punto, esperamos que sea seguido por más dígitos / exponente, o que no nos siga nada. Sin embargo, y esta es la parte importante, el punto es parte del número . Recuerda esto mientras nos movemos para ver cómo se obj.prop
operador punto, obj.prop
.
La Sección 11.2.1, Acceso a la propiedad describe la notación de puntos y corchetes para el acceso de los miembros:
MemberExpression . IdentifierName
CallExpression
es para llamadas a funciones, lo cual no nos importa. Observe cómo esperamos un MemberExpression
(que puede ser un DecimalLiteral
, pero no tome mi palabra, mire y vea si estoy en lo cierto).
¿Ves ese pequeño punto? Es lógico adelantarse y decir "bueno, aquí hay un punto en el esquema ... y hay un punto en 4.foo
por eso ... ¿por qué hay un error?" ¡Ay, mi hipotético amigo a quien uso para estas oraciones, olvidaste cómo se ve el DecimalLiteral
! Veamos dos ejemplos y veamos qué pasa.
42.foo
^
El cursor representa el personaje en el que estamos. Hasta ahora, estamos dentro de DecimalLiteral / DecimalIntegerLiteral / NonZeroDigit
(eso es bastante DecimalLiteral / DecimalIntegerLiteral / NonZeroDigit
). Pasemos al siguiente personaje:
42.foo
^
Todavía forma parte del número, un DecimalDigit
perfectamente válido.
42.foo
^
ok, entonces estamos fuera de la parte DecimalIntegerLiteral
. Aquí está el mismo diagrama en el esquema:
DecimalIntegerLiteral . DecimalDigits(opt) ExponentPart(opt)
^
Así que estamos en un punto, que es una parte perfectamente válida de un número. Ahora lo consumimos, como parte del número , y seguimos adelante:
42.foo
^
f
no es parte de DecimalDigits
ni de ExponentPart
, ahora estamos fuera del número. ¿Y ahora qué? ¿Qué es eso? No es parte de nada. Tal vez es un elemento de acceso a la propiedad? Echemos un vistazo al esquema:
MemberExpression . IdentifierName
^
Definitivamente estamos en MemberExpression
, pero no tenemos un punto que lo siga, ese punto ya es parte del número. Hemos llegado a un error sintáctico: dejamos de ejecutar y lo lanzamos. Con suerte no vives en una casa de cristal.
Espero que ahora entiendas por qué 42..foo
funciona. Una vez que salimos de MemberExpression
, enfrentamos otro punto:
42..foo
^
MemberExpression . IdentifierName
^
Seguido por un IdentifierName
Nombre perfectamente legal.
Por supuesto, hay varias otras maneras de separar el punto del número. Una forma, como lo demostró, es rodear el literal entre paréntesis: (42).foo
. Cuando alcanzamos el paréntesis, salimos de MemberExpression
y MemberExpression
en el punto. Otra forma es insertar un espacio: 42 .foo
, ya que un espacio no puede ser parte del número, y es neutral para el analizador, por lo que no generará un error.