¡Juguemos un poco más!
Primero, ¡divirtámonos !:
//----------#01#-----------
{}[true]; //[true]
//----------#02#-----------
var a = {}[true];
console.log(a); //undefined
//----------#03#-----------
{ b: 12345 }[true]; //[true]
//----------#04#-----------
{ b: 12345 }["b"]; //evaluates to ["b"] ?!?
//----------#05#-----------
{ b: 12345 }.b; // "Unexpected token ."
//----------#06#-----------
({ b: 12345 }).b; //12345
//----------#07#-----------
var c = { b: 12345 }.b;
console.log(c); //12345
//----------#08#-----------
var c = { b: 12345 }["b"];
console.log(c); //12345
//----------#09#-----------
{ true: 54321 }[true]; // "SyntaxError: Unexpected token : "
//----------#10#-----------
var d = { true: 54321 }[true]; //No error here ¬¬
console.log(d); //54321
//----------#11#-----------
!{}[true]; // true
Ok, tratemos de entender estos comportamientos locos, uno por uno:
1) Aquí, el {}se analiza como un bloque de código vacío. Sin una asignación, negación, agrupación (con paréntesis) o cualquier sintaxis que indique al analizador que este {}es un objeto literal, la suposición predeterminada es pensar que es simplemente un bloque vacío inútil.
Esta es una prueba de este comportamiento:
{ alert(123) }[true]
El código anterior mostrará la alerta normalmente y se evaluará como [true], de la misma manera {}[true].
Declaraciones de bloque sin punto y coma
Una declaración de tipo bloque no necesita un punto y coma después de ella.
Por ejemplo:
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
Se muestran ambas alertas.
Entonces, podemos ver que una declaración de bloque vacía, sin punto y coma, es válida y simplemente no hace nada. De esta manera, cuando ingrese {}[true]en la consola de herramientas de desarrollador (o Firebug), el valor evaluado será el valor de la última declaración de expresión . En este caso, la última declaración de expresión es [true].
2) En un contexto de asignación, el analizador se asegurará de que {}sea un objeto literal. Cuando haces var a = {}[true], eliminas cualquier ambigüedad y avisas al analizador que {}no es una declaración de bloque.
Entonces, aquí, estás tratando de obtener un valor con una clave "true"de un objeto vacío. Obviamente, no hay un par clave-valor con este nombre clave. De esta manera, la variable a no está definida.
Palabras reservadas como claves de objeto
ECMAScript 5 permite que las claves de objeto sean palabras reservadas. Entonces, las siguientes claves son legales:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) La misma explicación del ejemplo 1 . Pero ... Si la { b: 12345 }parte se trata como una declaración de bloque, ¿cuál es el tipo de b: 12345declaración?
... (?????)
Es una declaración de etiqueta , ya la viste antes ... Se usa en bucles y adentro switch. Aquí hay algunos enlaces interesantes sobre declaraciones de etiquetas: 1 , (2) [¿La mejor manera de romper los bucles anidados en Javascript? , (3) [ ¿Cómo romper bucles anidados en javascript? .
NOTA: solo trate de evaluar esto:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
Las declaraciones de etiquetas no pueden ser separadas por el operador de coma , necesitaría separarlas con un punto y coma. Entonces esto es válido:{a: 1; b: 2}
4) Véanse las explicaciones de los ejemplos 1 y 3 ...
5) Una vez más, se nos { b: 12345 }trata como un bloque de código, y está intentando acceder a una propiedad de un bloque de código utilizando la notación de puntos , y obviamente, esto no está permitido, y el analizador arroja una "Unexpected token :"excepción.
6) El código es casi idéntico al ejemplo anterior, pero al rodear la { b: 12345 }declaración con el operador de agrupación de expresiones , el analizador sabrá que es un objeto. De esta manera, podrá acceder a la "b"propiedad normalmente.
7) Recuerde el ejemplo 2 , tenemos una asignación aquí, el analizador sabe que { b: 12345 }es un objeto.
8) Idéntico al ejemplo anterior, pero en lugar de la notación de puntos, aquí estamos usando la notación de corchetes .
9) Ya dije que esta "identifier: value"sintaxis dentro de una declaración de bloque es una etiqueta. Pero también debe saber que un nombre de etiqueta no puede ser una palabra clave reservada (lo opuesto a los nombres de propiedad de objeto). Cuando intentamos definir una etiqueta llamada "true", obtuvimos un SyntaxError.
10) Nuevamente, estamos tratando con un objeto. No hay problemas al usar palabras reservadas aquí. =)
11) Finalmente, tenemos esto:!{}[true]
Separemos las cosas aquí:
a) Al hacer una negación, estamos informando al analizador que {}es un objeto .
b) Como se muestra en el ejemplo 2 , un {}objeto no tiene una propiedad llamada true, por lo que esta expresión se evaluará como undefined.
c) El resultado final es la negación del undefinedvalor. Javascript realiza una conversión de tipo de implicidad , y el undefinedvalor es falso .
d) Entonces, la negación de falsees ... true!
var o = {}; o[true] === undefined.