(! [] + []) [+ []]… Jelaskan mengapa ini berhasil

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

Output dari kode ini adalah: fail. Mengapa?

Ngomong-ngomong (![]+[])[+!+[]] == 'false'[1], kan ?. Tapi kenapa ![]+[] == "false"dan kenapa +!+[] == 1?

cdxf
sumber
14
@Noob Saya tidak percaya Anda. Pada akhirnya, itu adalah bom garpu.
Johannes Schaub - litb
3
Ini literal string, tentu saja;)
Yi Jiang
3
(![]+[])[+[]]adalah "f" (karakter pertama dari "false"), (![]+[])[+!+[]]adalah "a", dll.
Mauricio Scheffer
3
@Snoob: seperti yang Anda katakan, Anda dapat menguji setiap ekspresi di browser Anda. Coba alert(![]+[])kemudian alert(+!+[])dan Anda akan melihat.
Mauricio Scheffer
12
Tidak berguna atau tidak, saya menganggapnya sebagai pertanyaan yang menarik dan ingin melihat penjelasan yang tepat. Banyak Code Golf akan ditutup jika kegunaan atau kepraktisannya dipertimbangkan. Latihan dan permainan berguna untuk mengembangkan pikiran dan proses berpikir.
John K

Jawaban:

127

Seperti yang dikomentari oleh @Mauricio (![]+[])[+[]]adalah "f" (karakter pertama dari "false"), (![]+[])[+!+[]])adalah "a", dll ...

Bagaimana cara kerjanya?

Mari kita periksa karakter pertama, 'f':

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

Bagian pertama dari ekspresi-antara kurung-disusun oleh ![]+[], operan pertama operator Penambahan ini ![]dan itu akan menghasilkan false, karena obyek-sebagai array yang setiap Obyek lain misalnya-adalah truthy , dan menerapkan Logical (!) TIDAK unary operator, itu menghasilkan nilai false, misalnya.

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

Setelah itu, kita memiliki operan kedua tambahan, Array kosong [], ini dibuat hanya untuk mengubah falsenilai menjadi String, karena representasi string dari array kosong hanyalah string kosong, setara dengan:

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

Bagian terakhir, pasangan tanda kurung siku setelah tanda kurung, mereka adalah pengakses properti, dan mereka menerima ekspresi, yang dibentuk oleh Operator Unary Plus yang diterapkan ke array kosong lagi.

Apa yang dilakukan oleh Unary Plus Operator adalah konversi tipe Number, sebagai contoh:

typeof +"20"; // "number"

Sekali lagi, ini diterapkan ke Array kosong, dan seperti yang saya katakan sebelumnya, representasi String dari Array adalah string kosong, dan ketika Anda mengonversi string kosong menjadi Angka, itu diubah menjadi nol:

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

Oleh karena itu, kita dapat "mendekode" ekspresi menjadi dalam beberapa langkah:

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

Perhatikan bahwa mengakses karakter dengan menggunakan notasi braket pada nilai String bukanlah bagian dari ECMAScript ke-3. Spesifikasi Edisi, (itulah mengapa filecharAt metode ini ada).

Namun, jenis "properti indeks" yang mewakili karakter string ini distandarisasi pada ECMAScript 5, dan bahkan sebelum standarisasi fitur tersebut tersedia di sejumlah browser yang baik (bahkan dalam IE8 (mode standar)).

CMS
sumber
46
Berharap saja ini bukan pertanyaan wawancara.
Inisheer
4
@JTA: Saya berharap itu adalah ! Saya akan lulus :-D
Mauricio Scheffer
18
Dari manakah "i" itu berasal?
Josh Stodola
5
@rlemon, tidak ada inttipe data pada bahasa tersebut, pada kenyataannya semua angka dalam format 64-bit presisi ganda (nilai IEEE 754), meskipun beberapa operator bekerja secara internal dengan nilai Integer (seperti operator bitwise) hasilnya selalu ganda . Contoh ini 'i'berasal dari undefined, tetapi bisa berasal dari Infinitymisalnya: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS
5
@JoshStodola Nah, ~ 3 bulan kemudian, klarifikasi lebih lanjut. "I" dalam hal ini berasal dari "tidak terdefinisi", ya, tapi ada trik lain yang terlibat di sini. Kode tersebut menggabungkan "false" menjadi "undefined" menjadi bentuk "falseundefined"(dibangun menggunakan [![]]+[][[]]:) di mana indeks "i" adalah 10. +!+[]+[+[]]memberikan "10". Ini digunakan untuk mengekstrak "i" (Indeks string dapat digunakan dalam javascript jika mereka dapat dipaksa menjadi bilangan bulat). Konstruksi terakhir yang menghasilkannya adalah:([![]]+[][[]])[+!+[]+[+[]]]
entropi