2012-03-29 6 views
9

En la consola de ambos FF y Chrome, {} se considera indefinido hasta que sea evaluado de forma explícita:¿Cuándo (y por qué) {} está indefinido en una consola de JavaScript?

{};  // undefined 
({}); // ▶ Object 

En realidad, es un poco menos definidos que no definido - es aparentemente mala sintaxis:

{} === undefined; // SyntaxError: Unexpected token === 
{}.constructor; // SyntaxError: Unexpected token . 

pero no si está en el otro lado, en cuyo caso está bien:

"[object Object]" == {}.toString(); // true 

O si no es la primera expresión:

undefined + undefined; // NaN 
{} + undefined;  // NaN 
undefined + {};  // "undefined[object Object]" 

¿Qué ofrece?

+6

... ¿Qué es f {INDEFECHIDO}? no es realmente tan apropiado. ¿Puedes reformular? –

+0

Las consolas no necesariamente se asignan explícitamente a JS normales. Sé por ejemplo que (no recuerdo si esta era la consola de Chrome o FF) que si escribe '$ (id)' lo evaluaría como 'document '.getElementById (id) '(que se rompería con jQuery, por ejemplo). – Alxandr

Respuesta

6

Bien, esta es mi respuesta. No hay nada nuevo aquí. Acabo de vincular (una copia bonita de) la especificación ECMAScript para la gramática y mostrar algunas producciones para mostrar "por qué" analiza la forma en que lo hace. En cualquier caso, el comportamiento está bien definido de acuerdo con las reglas de la gramática Javascript/ECMAScript:. {} se analice de manera diferente dependiendo del "contexto" que se encuentra en


Las JavaScript REPL s ("consolas") inicio para analizar el código en la producción de gramática Statement o "contexto de declaración". (Esto es realmente una mentira, comienza en la producción Program o SourceElements, pero eso agrega construcciones adicionales para profundizar.) Aquí hay un desglose de gramática aproximada con simplificaciones y omisiones; ver el enlace anterior para obtener más:

Statement 
    Block 
    ... 
    ExpressionStatement 

Block 
    # This is actually { StatementList[optional] }, but this is what 
    # it amounts to: * means "0 or more". 
    { Statement* } 

ExpressionStatement 
    # An ExpressionStatement can't start with "{" or "function" as 
    # "{" starts a Block and "function" starts a FunctionStatement. 
    [lookahead ∉ {{, function}]Expression ; 

Expression 
    # This is really PrimaryExpression; I skipped a few steps. 
    ... 
    (Expression) 

Por lo tanto (cuando está en "contexto comunicado"):

{} 
-> Block # with no StatementList (or "0 statements") 
-> Statement 

Y:

({}) 
-> (Expression) 
-> Expression 
-> ExpressionStatement # omitted in productions below 
-> Statement 

Esto también explica por qué undefined === {} un análisis sintáctico como EXPR === EXPR -> EXPR -> STMT y resultados en falso cuando se evalúa. El {} en este caso está en un "contexto de expresión".

En el caso de {} === undefined se analiza como {}; === undefined, o BLOCK; BOGUS -> STMT; BOGUS, que es un error de sintaxis. Sin embargo, con la adición de paréntesis, esto cambia: ({} === undefined) se analiza como (EXPR === EXPR) -> (EXPR) -> EXPR -> STMT.

En el caso de {} + "hi" se analiza como {}; + "hi", o BLOCK; + EXPR -> STMT; EXPR -> STMT; STMT, que es una sintaxis válida a pesar de que es tonto (+ es unario en este caso). Del mismo modo, al igual que arriba, "hi" + {} pone el {} en un "contexto de expresión" y se analiza como EXPR + EXPR -> EXPR -> STMT.

La consola de JavaScript solo muestra el resultado de la última instrucción, que es "indefinida" (bueno, "nada" en realidad, pero eso no existe) para un bloque vacío {}. (Esto puede variar entre navegadores/entornos en cuanto a lo que se devuelve en este caso, por ejemplo, último ExpressionStatement solamente)

Happy coding.

1

Parece que ambas consolas lo tratan como una condición ambigua cuando la expresión comienza con {. Tal vez se trata como un bloque ficticio.

Prueba esto:

{} // undefined 
undefined === {} // false 

Usando {} como un derecho-expresión elimina la ambigüedad.

También se puede ver en:

{a:42} // 42 
{{a:42}} // 42 
{{{a:42}}} // 42 

Que los apoyos exteriores son realmente tratados como un disco de empuje.

Y esto no parece ser una función de consola. Incluso eval los trata como esa, haciendo alusión al hecho de que el material se escribe en la consola realmente se les evaluó la misma manera que lo harían cuando se pasa a eval:

eval("{}") // undefined 
eval("{alert(42)}") // alerts 42 
+0

{} === undefined es un SyntaxError, ¿por qué? –

+0

@JS_Riddler, por la misma razón esto es: '{alert (" hi ")} === undefined' –

+0

Lo siento, quise tener' {} 'solo. Corregí la respuesta. –

0

El problema es que en algunos casos, javascript ve { y} como abrir y cerrar a/block /. Mientras que en otros casos, {} es un objeto. Los casos realmente dependen del contexto.

10

Si utiliza los corchetes por sí solos, no es un objeto literal, es un bloque de código. Como el bloque de código no contiene ningún código, la evaluación da como resultado undefined.

+0

Lo mismo ocurre con las otras formas que funcionan: en esos casos, '{}' aparece como * expresión *. –

+0

Esto no explica cómo "{} === undefined" es un error de sintaxis, y "undefined === {}" no lo es. –

+1

@JS_Riddler Sí lo hace. '{} === undefined' se analiza como' {}; === undefined' as '{}' aparece en una ubicación donde * no * se lee como una expresión. '({} === undefined)' funcionaría. Esto se debe a que, en este último caso, el analizador lee el '{}' como un objeto literal ("como una expresión"). –

0

Doug Crockford se queja de esto. Esa WTF que está llegando se debe al operador + en sí. Está acostumbrado tanto a la aritmética como a la concatenación. En su última línea, está viendo que el operador + convierte indefinido y el objeto vacío en cadenas y concatenandolas.

+0

Este no es el problema en este caso. Pruebe: '{} +" falla porque {} es un bloque y no una expresión "' y '" bien porque {} ahora es una expresión "+ {}'. –

+0

No, los dos concatenan ... El primero evaluará que "[objeto Object] falla porque {} es un bloque y no una expresión" y el segundo "está bien porque {} ahora es una expresión [object Object]" –

+0

@ pst: no es un error de sintaxis el primero en realidad es: '{}; + "somestring" .. '. que intenta convertir la secuencia al número y obtienes 'NaN' –

2

Si escribe {} como entrada en cualquier consola, no hay contexto para interpretar lo que quiere que signifiquen las llaves, aparte de su posición. dado que cada entrada a la consola se interpreta como una nueva línea de código, la llave de apertura se ve como el inicio de un nuevo bloque. El cierre } es sintácticamente correcta, ya que un bloque vacío se utiliza a menudo en situaciones como estas:

try 
{ 
    //something 
} 
catch(e) 
{}//suppress error 

Por lo tanto {} siempre estarán indefinidos cuando está en el lado izquierdo, y nunca escupir errores como un bloque vacío es codigo valido.

+0

@pst, cierto ... He editado mi respuesta. –

0

Javascript separa el concepto de enunciados y expresiones (los lenguajes como C++ o Java hacen lo mismo). Por ejemplo, if ... es una afirmación y x?y:z es una expresión.

Las expresiones tienen un valor, las declaraciones no.

Un problema con la sintaxis de Javascript es que {} puede ser una expresión (y en este caso significa un constructor de objetos vacío) o una declaración (y en este caso significa un bloque de código vacío ... básicamente un NOP) entonces, cómo se interpreta depende del contexto.

Cuestiones relacionadas