{}[true]
es [true]
y ![true]
debe ser false
.
Entonces, ¿por qué !{}[true]
evaluar a true
?
javascript
usuario2430508
fuente
fuente
var o = {}; o[true] === undefined
.{}[true] === [true]
de una consola, es porque se trata{}
como un bloque de código vacío, no como un objeto.{}
y({})
en su consola (o{}[true]
y({})[true]
). Además, como nadie lo mencionó, el objeto [verdadero] se evalúa como objeto ["verdadero"].Respuestas:
Creo que eso se debe a que plain
{}[true]
se analiza como un bloque de instrucciones vacío (no un literal de objeto) seguido de una matriz que contienetrue
, que estrue
.Por otro lado, la aplicación del
!
operador hace que el analizador interprete{}
como un objeto literal, por lo que lo siguiente se{}[true]
convierte en un acceso de miembro que devuelveundefined
, y de!{}[true]
hechotrue
(como!undefined
estrue
).fuente
undefined
es falso (algo en lo que confiamos a menudoif (obj.maybeExists) ...
), por lo que tiene mucho sentido lógico que!undefined
sea cierto.null
en algunos idiomas, con!undefined
ser igual aundefined
. Sin embargo, ese no es el caso en Javascript.not undefined
(!undefined
), por lo tanto, debe definirse. Si algo se define, generalmente se interpreta comotrue
.Porque
{}[true]
no regresatrue
, peroundefined
, yundefined
se evalúa comofalse
:http://jsfiddle.net/67GEu/
fuente
{}[true]
en una consola, obtiene[true]
, porque{}
se interpreta como un bloque de código vacío, no como un objeto. Se trata del contexto y la ambigüedad de{}
.{key:"value"}[1,2,3];
también evalúa[1,2,3]
?key:
) y un literal de cadena ("value"
), seguido de una matriz. El analizador aún no ve un objeto literal.alert()
oconsole.log()
, o lo asigna a una variable, está cambiando el contexto, por lo que no se comporta de la misma manera que se escribe solo en una consola.Porque
evalúa a
undefined
, y!undefined
estrue
.De @schlingel:
true
se usa como clave y{}
como mapa hash. No existe una propiedad con la clave,true
por lo que se devuelveundefined
. Noundefined
estrue
, como se esperaba.Sesión de consola ( Node.js
[0.10.17]
):Sin embargo, en la consola Google Chrome :
Entonces, no hay inconsistencias. Probablemente esté utilizando una versión anterior de la máquina virtual de JavaScript. Para aquellos que necesitan más evidencia:
ACTUALIZAR
Con Firefox , también se evalúa para
true
:fuente
eval('{}[true]')
o lo escribes en la consola. Entonces, por ejemplo, als{}"test"
estest
o incluso{key:"value"}"test"
estest
.{}[true];
(Con el;
) vuelve[true]
por ti, porque aquí lo hace?La razón de la confusión se debe a un malentendido de su primera afirmación:
{}[true]
es[true]
Lo que ves cuando lo ejecutas es el resultado de una ambigüedad. Javascript tiene un conjunto definido de reglas sobre cómo manejar ambigüedades como esta, y en este caso, divide lo que ve como una declaración de señalización en dos declaraciones separadas.
Entonces, Javascript ve el código anterior como dos declaraciones separadas: en primer lugar, hay un
{}
, y luego hay un completamente separado[true]
. La segunda afirmación es lo que te está dando el resultado[true]
. La primera declaración{}
es efectivamente ignorada por completo.Puede probar esto intentando lo siguiente:
es decir, envolver todo entre paréntesis para obligar al intérprete a leerlo como una sola declaración.
Ahora verá que el valor real de su estado de cuenta es
undefined
. (Esto también nos ayudará más tarde a comprender la siguiente parte)Ahora sabemos que la parte inicial de su pregunta es una pista falsa, así que pasemos a la parte final de la pregunta:
Aquí, tenemos la misma declaración, pero con un
!
anexo al frente.En este caso, las reglas de Javascript le dicen que evalúe todo como una sola declaración.
Refiérase a lo que sucedió cuando envolvimos la declaración anterior entre paréntesis; llegamos
undefined
. Esta vez, efectivamente estamos haciendo lo mismo, pero poniendo un!
frente a eso. Entonces su código puede simplificarse como!undefined
, que estrue
.Esperemos que eso lo explique un poco.
Es una bestia compleja, pero la lección que debe aprender aquí es usar corchetes alrededor de sus declaraciones al evaluarlas en la consola, para evitar resultados espurios como este.
fuente
{}[true]
sea inválido exactamente, solo ambiguo . Puede interpretarse como "bloque de código vacío seguido de literal de matriz" o "literal de objeto sin propiedades, al que se accede a una propiedad". No sé si el primero es técnicamente un caso de ASI (de todos modos, muchos idiomas no pondrían un punto y coma), pero es la interpretación sensible al contexto el núcleo del problema.{}[true]
estrue
", dijeron "{}[true]
es[true]
", que es una de las dos interpretaciones válidas de la declaración ambigua.{}[true]
esundefined
. Para encontrar eso escribe esto:o simplemente:
Sabemos que
!undefined
estrue
.De la respuesta de @Benjamin Gruenbaum :
Se puede encontrar más información en esta pregunta .
fuente
Las respuestas aquí son buenas, aquí hay un desglose en pseudocódigo:
{}['whatever']
= bloque vacío, NewArray ('lo que sea') = NewArray ('lo que sea'){}[true]
= bloque vacío, NewArray (true) = NewArray (true)!{}['whatever']
= LogicalNOT (convertToBool (NewObject.whatever)) = LogicalNOT (convertToBool (undefined)) = LogicalNOT (false) = verdadero({}['whatever'])
= Agrupación (NewObject.whatever) = Agrupación (indefinido) = indefinidofuente
Esto sucede porque,
{}
en su significado, no es una presentación literal deObject
, sino un alcance vacío (o un bloque de código vacío):Simplemente evalúa el código dentro del alcance y luego le muestra su matriz.
Y de tu
Simplemente convierte a int este alcance y devuelve la misma matriz verdadera. No hay cheques de bool en este código.
Y si intenta comprobar el resultado
{}[true]
, obtendrá sufalse
:Como ya no hay más alcance.
Entonces,
!
en su pregunta, haga lo mismo que:fuente
var x = {}; x[true]
.!
que se interpreta como un objeto vacío, no alcance, y esta es la discrepancia.{}
es un objeto sin propiedades.[]
sigue inmediatamente a un objeto, significa "Acceder a una propiedad de este nombre" y no "Crear una matriz"true
es un booleano, pero se está utilizando como un nombre de propiedad, por lo que se convierte en una cadena ("true"
)true
(ya que no tiene propiedades) por lo que{}['true']
esundefined
!undefined
se convierteundefined
en un booleano (false
)false
entrue
.fuente
{}[true]
(sin otro contexto), no{}
es un objeto sin propiedades, es un bloque de código vacío.No estás invirtiendo el valor de la misma.
Mira esto: ¿Por qué es cierto? 'falso': 'verdadero' que devuelve 'verdadero'?
fuente
¡Juguemos un poco más!
Primero, ¡divirtámonos !:
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:
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:
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:
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 deb: 12345
declaració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:
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 unSyntaxError
.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 llamadatrue
, por lo que esta expresión se evaluará comoundefined
.c) El resultado final es la negación del
undefined
valor. Javascript realiza una conversión de tipo de implicidad , y elundefined
valor es falso .d) Entonces, la negación de
false
es ...true
!fuente