ventajas funciona español ejemplos desventajas descargar definicion como caracteristicas javascript

funciona - ¿Por qué!{}[Verdadero] evalúa como verdadero en JavaScript?



javascript español (10)

¡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, intentemos 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.

Esto 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 que {}[true] .

Declaraciones de bloques sin puntos y coma

Una instrucción de tipo bloque no necesita un punto y coma después.

Por ejemplo:

for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")

Ambas alertas se muestran.

Entonces, podemos ver que una instrucción de bloque vacío, sin punto y coma, es válida y simplemente no hace nada. De esta forma, cuando ingrese {}[true] en la consola de Herramientas de desarrollo (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 le das la propina al analizador que {} no es una instrucción de bloque.
Entonces, aquí está tratando de obtener un valor con una clave "true" de un objeto vacío. Obviamente, no hay un par clave-valor con este nombre de clave. De esta manera, la variable a es indefinida.

Palabras reservadas como claves de Objeto

ECMAScript 5 permite que las claves de objetos 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 parte { b: 12345 } se trata como una instrucción de bloque, ¿cuál es el tipo de la instrucción b: 12345 ?

... (?????)

Es una declaración de etiqueta , ya lo viste antes ... Se usa en bucles y en el 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 trata de evaluar esto:

{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :

El operador de comma no puede separar las declaraciones de etiqueta, debe separarlas con un punto y coma. Entonces esto es válido: {a: 1; b: 2} {a: 1; b: 2}

4) Ver las explicaciones para los ejemplos 1 y 3 ...

5) Una vez más, tenemos un { b: 12345 } siendo tratado como un bloque de código, y está tratando de acceder a una propiedad de un bloque de código mediante el uso de la notación de punto , y obviamente, esto no está permitido, y el El analizador arroja una excepción de "Unexpected token :" .

6) El código es casi idéntico al ejemplo anterior, pero rodeando la declaración { b: 12345 } con el operador de agrupación de expresiones , el analizador sabrá que es un objeto. De esta manera, podrás acceder a la propiedad "b" normalmente.

7) Recuerde el ejemplo 2 , tenemos una tarea 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 sintaxis de "identifier: value" dentro de una declaración de bloque es una etiqueta. Pero también debe saber que el nombre de una etiqueta no puede ser una palabra clave reservada (lo contrario de los nombres de propiedad del objeto). Cuando tratamos de definir una etiqueta llamada "true" , obtuvimos un SyntaxError .

10) De nuevo, estamos lidiando con un objeto. No hay problemas para usar palabras reservadas aquí. =)

11) Finalmente, tenemos esto !{}[true]

Vamos a separar las cosas aquí:

a) Al hacer una negación, estamos informando al analizador que el {} 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 de undefined valor undefined . Javascript realiza conversión de tipo de implicidad y el valor undefined es falso .

d) Entonces, la negación de lo false es ... ¡ true !

{}[true] es [true] y ![true] debería ser false .

Entonces, ¿por qué !{}[true] evalúa a true ?


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 contiene true , que es true .

Por otro lado, aplicando el ! el operador hace que el analizador interprete {} como un objeto literal, por lo que el siguiente {}[true] convierte en un acceso de miembro que devuelve undefined , y !{}[true] es de hecho true (ya que !undefined es true ).


Esto sucede porque {} en su significado no es una presentación literal de Object , sino un alcance vacío (o un bloque de código vacío):

{ var a = 1 }[true] // [true] (do the same thing)

Simplemente evalúa el código dentro del alcance y luego te muestra tu matriz.

Y de tu

!{}[true]

Simplemente convierte a int este ámbito y devuelve la misma matriz verdadera. No hay controles bool en este código.

Y si intentas verificar el resultado de {}[true] obtendrás tu false :

{}[true] -> [true] -> ![true] -> false

Como ya no hay más alcance.

Entonces ! en tu pregunta haz lo mismo que:

!function() { //... }


La razón de la confusión se debe a un malentendido de su primera afirmación:

{}[true] es [true]

Lo que estás viendo 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, rompe lo que usted ve como una declaración de signle en dos declaraciones separadas.

Entonces, Javascript ve el código anterior como dos declaraciones separadas: en primer lugar, hay un {} , y luego hay un [true] completamente [true] completamente diferente. La segunda declaración es la que te está dando el resultado [true] . El primer enunciado {} es efetivamente completamente ignorado.

Puedes probar esto probando lo siguiente:

({}[true])

es decir, envolviendo todo entre corchetes para obligar al intérprete a leerlo como una sola declaración.

Ahora verá que el valor real de su extracto undefined está undefined . (Esto también nos ayudará luego a entender 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:

Entonces, ¿por qué! {} [Verdadero] evalúa a verdadero?

Aquí, tenemos la misma declaración, pero con a ! anexa al frente de ella.

En este caso, las reglas de Javascript le dicen que evalúe todo como una declaración única.

Refiérase a lo que sucedió cuando cerramos la declaración anterior entre corchetes; estamos undefined Esta vez, efectivamente estamos haciendo lo mismo, ¡pero poniendo un ! en frente de eso. Por lo tanto, su código se puede simplificar como !undefined , lo cual es true .

Espero que eso lo explique un poco.

Es una bestia compleja, pero la lección para aprender aquí es usar corchetes alrededor de sus declaraciones al evaluarlas en la consola, para evitar resultados espurios como este.


Las respuestas aquí son buenas, aquí hay un desglose en pseudo-código:

  • {}[''whatever''] = bloque vacío, NewArray (''whatever'') = NewArray (''whatever'')
  • {}[true] = bloque vacío, NewArray (verdadero) = NewArray (verdadero)
  • !{}[''whatever''] = LogicalNOT (convertToBool (NewObject.whatever)) = LogicalNOT (convertToBool (undefined)) = LogicalNOT (false) = true
  • ({}[''whatever'']) = Agrupación (NewObject.whatever) = Agrupación (indefinido) = indefinido


Porque

{}[true]

se evalúa como undefined , y !undefined es true .

De @schlingel:

true se usa como clave y {} como hash map. No existe una propiedad con la clave true por lo que devuelve undefined . No undefined es true , como se esperaba.

Sesión de consola ( Node.js [0.10.17] ):

> {}[true] undefined > !{}[true] true > [true] [ true ] > ![true] false >

Sin embargo, en la consola de Google Chrome :

> !{}[true] true

Entonces, no hay inconsistencias. Probablemente estés usando una versión anterior de la VM de JavaScript. Para aquellos que necesitan más evidencia:

ACTUALIZAR

Con Firefox , también se evalúa como true :


Porque {}[true] no devuelve true , pero undefined , e undefined se evalúa como false :

http://jsfiddle.net/67GEu/

''use strict''; var b = {}[true]; alert(b); // undefined b = !{}[true]; alert(b); // true


{}[true] undefined está undefined . Para encontrar eso escribe esto:

a = {}; a[true] === undefined // true

o simplemente:

({})[true] === undefined // true

Sabemos que !undefined es true .

De la respuesta de @Benjamin Gruenbaum :

Las herramientas de Chrome dveloper hacen lo siguiente :

try { if (injectCommandLineAPI && inspectedWindow.console) { inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null); expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {/n" + expression + "/n}"; } var result = evalFunction.call(object, expression); if (objectGroup === "console") this._lastResult = result; return result; } finally { if (injectCommandLineAPI && inspectedWindow.console) delete inspectedWindow.console._commandLineAPI; }

Básicamente, realiza una call al objeto con la expresión. La expresión es:

with ((window && window.console && window.console._commandLineAPI) || {}) { {}+{};// <-- This is your code }

Entonces, como puede ver, la expresión se está evaluando directamente, sin el paréntesis de ajuste.

Se puede encontrar más información en esta pregunta .


  • {} es un objeto sin propiedades.
  • Como [] sigue inmediatamente a un objeto, significa "Acceder a una propiedad de este nombre" y no "Crear una matriz"
  • true es un booleano, pero se usa como nombre de propiedad, por lo que se convierte en una cadena ( "true" )
  • El objeto no tiene una propiedad llamada true (ya que no tiene propiedades) por lo que {}[''true''] undefined está undefined
  • !undefined cast undefined !undefined undefined a booleano ( false )
  • El operador no convierte false en true .