(! [] + []) [+ []]… Bunun neden işe yaradığını açıklayın


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

Bu kodun çıktısı şöyledir: fail. Neden?

Bu arada (![]+[])[+!+[]] == 'false'[1], değil mi? Ama neden ![]+[] == "false"ve neden +!+[] == 1?


14
@Snoob sana güvenmiyorum. Sonunda çatallı bir bomba.
Johannes Schaub -

3
Elbette bu bir dizi değişmez;)
Yi Jiang

3
(![]+[])[+[]]"f" ("yanlış" dan ilk karakter), (![]+[])[+!+[]]"a", vb.
Mauricio Scheffer

3
@Snoob: Dediğiniz gibi, tarayıcınızda her bir ifadeyi test edebilirsiniz. alert(![]+[])O zaman dene alert(+!+[])ve göreceksin.
Mauricio Scheffer

12
Yararsız olsun ya da olmasın, bunu ilginç bir soru buluyorum ve iyi yazılmış bir açıklama görmek istiyorum. Yararlılık veya pratiklik dikkate alınırsa, birçok Code Golf kapalı olacaktır. Egzersizler ve oyunlar, zihni ve düşünme sürecini genişletmek için kendi başlarına faydalıdır.
John K

Yanıtlar:


127

@Mauricio'nun yorumladığı gibi (![]+[])[+[]]"f" ("yanlış" ın ilk karakteri), (![]+[])[+!+[]])"a", vb ...

O nasıl çalışır?

İlk karakter olan 'f'yi inceleyelim:

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

İfadenin ilk kısmı - parantezler arasında - ![]+[], Toplama operatörünün ilk işleneni tarafından oluşturulur ![]ve üretecektir false, çünkü bir dizi nesnesi - diğer herhangi bir Nesne örneği gibi - doğrudur ve Mantıksal (!) NOT tekli operatör, falseörneğin değeri üretir .

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

Ondan sonra, toplamanın ikinci işlenenine sahibiz, boş bir Dizi, []bu sadece falsedeğeri String'e dönüştürmek için yapılır , çünkü boş bir dizinin dize temsili sadece boş bir dizedir, şuna eşdeğerdir:

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

Son kısım, parantezlerden sonra köşeli parantez çifti, bunlar özellik erişimcisidir ve Unary Plus Operatörünün boş bir diziye tekrar uyguladığı bir ifade alırlar.

Unary Plus Operatörünün yaptığı şey Number, örneğin aşağıdakilere tür dönüştürmedir :

typeof +"20"; // "number"

Bir kez daha, bu boş bir Diziye uygulanır ve daha önce de söylediğim gibi, bir Array'in Dize temsili boş bir dizedir ve boş bir dizeyi Number'a dönüştürdüğünüzde, sıfıra dönüştürülür:

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

Bu nedenle, ifadeyi bazı adımlarda "çözebiliriz":

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

Dize değerlerinde köşeli parantez gösterimini kullanarak karakterlere erişmenin ECMAScript 3'ün bir parçası olmadığını unutmayın. Sürüm Spesifikasyonu, ( charAtyöntem bu yüzden mevcuttu).

Bununla birlikte, bir dizenin karakterlerini temsil eden bu tür "dizin özellikleri", ECMAScript 5'te standartlaştırılmıştır ve standardizasyondan önce bile özellik, çok sayıda tarayıcıda mevcuttur (hatta IE8'de (standartlar modu)).


46
Umarım bu asla bir röportaj sorusu değildir.
Inisheer

4
@JTA: Ben umut olduğunu ! Geçerdim :-D
Mauricio Scheffer

18
"İ" nereden geliyor?
Josh Stodola

5
@rlemon, intdilde veri türü yoktur , aslında tüm sayılar çift duyarlıklı 64-bit formattır (IEEE 754 değerleri), bazı operatörler dahili olarak Tamsayı değerleriyle çalışsa da (bitsel operatörler gibi) sonuç her zaman bir çifttir . 'i'Bu örnekte geliyor undefined, ama gelebilir Infinityörneğin: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS

5
@JoshStodola Peki, ~ 3 ay sonra, bir açıklama daha. Bu durumda "i" "tanımlanmamış" dan geliyor, evet, ama burada başka bir numara var. Kod , "i" dizininin 10 olduğu form "falseundefined"(: kullanılarak oluşturulur) için "yanlış" ı "tanımsız" ile birleştirir [![]]+[][[]]. +!+[]+[+[]]Verir "10". Bu, "i" yi çıkarmak için kullanılır (Dize indeksleri, görünüşte tam sayılara zorlanabiliyorlarsa, javascript'te kullanılabilir). Onu üreten son yapı:([![]]+[][[]])[+!+[]+[+[]]]
entropi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.