(! [] + []) [+ []]… Spiega perché funziona


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

L'output di questo codice è: fail . Perché?

A proposito (![]+[])[+!+[]] == 'false'[1], giusto? Ma perché ![]+[] == "false"e perché +!+[] == 1?


14
@ Snoob Non mi fido di te. Alla fine, è una bomba a forcella.
Johannes Schaub - litb

3
È una stringa letterale, ovviamente;)
Yi Jiang

3
(![]+[])[+[]]è "f" (il primo carattere di "false"), (![]+[])[+!+[]]è "a", ecc.
Mauricio Scheffer

3
@Snoob: come hai detto, puoi testare ogni espressione sul tuo browser. Prova alert(![]+[])allora alert(+!+[])e vedrai.
Mauricio Scheffer

12
Inutile o no, trovo che sia una domanda interessante e vorrei vedere una spiegazione ben formulata. Molti Code Golf sarebbero chiusi se si considerasse l'utilità o la praticità. Esercizi e giochi sono utili di per sé per espandere la mente e il processo di pensiero.
John K

Risposte:


127

Come ha commentato @Mauricio (![]+[])[+[]]è "f" (il primo carattere di "false"), (![]+[])[+!+[]])è "a", ecc ...

Come funziona?

Esaminiamo il primo carattere, "f":

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

La prima parte dell'espressione, tra parentesi, è composta da ![]+[], il primo operando dell'operatore Addition è ![]e produrrà false, perché un oggetto array, come qualsiasi altra istanza di Object, è vero e applica il Logical (!) NOT unario operatore, produce il valore false, ad esempio.

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

Dopo di esso, abbiamo il secondo operando dell'addizione, un Array vuoto [], questo viene fatto solo per convertire il falsevalore in String, perché la rappresentazione di stringa di un array vuoto è solo una stringa vuota, è equivalente a:

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

L'ultima parte, la coppia di parentesi quadre dopo le parentesi, sono la funzione di accesso alla proprietà e ricevono un'espressione, che è formata dall'operatore Unario Plus applicato nuovamente a un array vuoto.

Quello che fa l'operatore Unary Plus è la conversione del tipo, ad Numberesempio:

typeof +"20"; // "number"

Ancora una volta, questo viene applicato a un array vuoto e, come ho detto prima, la rappresentazione di stringa di un array è una stringa vuota e quando converti una stringa vuota in Number, viene convertita a zero:

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

Quindi possiamo "decodificare" l'espressione in alcuni passaggi:

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

Si noti che l'accesso ai caratteri utilizzando la notazione tra parentesi sui valori String non faceva parte di ECMAScript 3 °. Specifiche dell'edizione, (ecco perché il filecharAt metodo esisteva).

Tuttavia questo tipo di "proprietà indice" che rappresentano i caratteri di una stringa erano standardizzate su ECMAScript 5, e anche prima della standardizzazione la funzionalità era disponibile in un buon numero di browser (anche in IE8 (modalità standard)).


46
Spero solo che questa non sia mai una domanda da intervista.
Inisheer

4
@ JTA: spero che lo sia ! Sarei passato MrGreen
Mauricio Scheffer

18
Da dove viene la "i"?
Josh Stodola

5
@rlemon, non c'è nessun inttipo di dato sulla lingua, infatti tutti i numeri sono in formato a 64 bit a doppia precisione (valori IEEE 754), anche se alcuni operatori lavorano internamente con valori Integer (come gli operatori bit a bit) il risultato è sempre un doppio . In 'i'questo esempio viene da undefined, ma potrebbe provenire da Infinity: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS

5
@JoshStodola Bene, ~ 3 mesi dopo, un ulteriore chiarimento. La "i" in questo caso deriva da "undefined", sì, ma qui è coinvolto un altro trucco. Il codice concatena "false" a "undefined" in forma "falseundefined"(costruita usando :) [![]]+[][[]]in cui l'indice di "i" è 10. +!+[]+[+[]]"10". Questo viene utilizzato per estrarre la "i" (gli indici di stringa possono essere utilizzati in javascript se possono essere forzati a interi apparentemente). Il costrutto finale che lo produce è:([![]]+[][[]])[+!+[]+[+[]]]
entropia
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.