(! [] + []) [+ []]… Explique por qué funciona

107
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);

El resultado de este código es: fail . ¿Por qué?

Por cierto (![]+[])[+!+[]] == 'false'[1], ¿no ?. Pero ¿ ![]+[] == "false"por qué y por qué +!+[] == 1?

cdxf
fuente
14
@Snoob, no confío en ti. Al final, es una bomba de horquilla.
Johannes Schaub - litb
3
Es una cadena literal, por supuesto;)
Yi Jiang
3
(![]+[])[+[]]es "f" (el primer carácter de "falso"), (![]+[])[+!+[]]es "a", etc.
Mauricio Scheffer
3
@Snoob: como dijiste, puedes probar cada expresión en tu navegador. Prueba alert(![]+[])entonces alert(+!+[])y verás.
Mauricio Scheffer
12
Inútil o no, me parece una pregunta interesante y me gustaría ver una explicación bien redactada. Muchos Code Golfs se cerrarían si se considerara la utilidad o la practicidad. Los ejercicios y los juegos son útiles en sí mismos para expandir la mente y el proceso de pensamiento.
John K

Respuestas:

127

Como comentó @Mauricio (![]+[])[+[]]es "f" (el primer carácter de "falso"), (![]+[])[+!+[]])es "a", etc ...

¿Como funciona?

Examinemos el primer carácter, 'f':

(![]+[])[+[]]; // 'f'

La primera parte de la expresión, entre paréntesis, está compuesta por ![]+[], el primer operando del operador de suma es ![]y producirá false, porque un objeto de matriz, como cualquier otra instancia de objeto, es veraz y aplica la lógica (!) NOT unaria operador, produce el valor false, por ejemplo.

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey

Después, tenemos el segundo operando de la suma, un Array vacío [], esto se hace solo para convertir el falsevalor a String, porque la representación de cadena de un arreglo vacío es solo una cadena vacía, es equivalente a:

false+[]; // "false"
false+''; // "false"

La última parte, el par de corchetes después del paréntesis, son el descriptor de acceso a la propiedad y reciben una expresión, que está formada por el Operador Unario Plus aplicado a una matriz vacía nuevamente.

Lo que hace el operador Unary Plus es la conversión de tipos Number, por ejemplo:

typeof +"20"; // "number"

Una vez más, esto se aplica a una matriz vacía y, como dije antes, la representación de cadena de una matriz es una cadena vacía, y cuando convierte una cadena vacía en número, se convierte a cero:

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0

Por lo tanto, podemos "decodificar" la expresión en algunos pasos:

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"

Tenga en cuenta que acceder a los caracteres mediante el uso de la notación de corchetes en los valores de cadena no formaba parte del ECMAScript 3rd. Especificación de la edición, (por esocharAt existía método).

Sin embargo, este tipo de "propiedades de índice" que representan los caracteres de una cadena se estandarizaron en ECMAScript 5, e incluso antes de la estandarización, la función estaba disponible en un buen número de navegadores (incluso en IE8 (modo estándar)).

CMS
fuente
46
Solo espero que esta nunca sea una pregunta de entrevista.
Inisheer
4
@JTA: ¡Espero que lo sea ! Habría aprobado :-D
Mauricio Scheffer
18
¿De dónde viene la "yo"?
Josh Stodola
5
@rlemon, no hay inttipo de datos en el idioma, de hecho, todos los números tienen un formato de 64 bits de doble precisión (valores IEEE 754), aunque algunos operadores trabajan internamente con valores enteros (como los operadores bit a bit), el resultado es siempre un doble . El 'i'viene en este ejemplo de undefined, pero podría provenir de Infinitypor ejemplo: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS
5
@JoshStodola Bueno, ~ 3 meses después, una aclaración adicional. La "i" en este caso proviene de "indefinido", sí, pero hay otro truco involucrado aquí. El código concatena "falso" a "indefinido" para formar "falseundefined"(construido usando :) [![]]+[][[]]en el que el índice de "i" es 10. +!+[]+[+[]]da "10". Esto se usa para extraer la "i" (los índices de cadenas se pueden usar en javascript si aparentemente se pueden convertir en números enteros). La construcción final que lo produce es:([![]]+[][[]])[+!+[]+[+[]]]
entropía