Kodėl ++ [[]] [+ []] + [+ []] grąžina eilutę „10“?

Tai galioja ir grąžina eilutę "10" „JavaScript“ ( daugiau pavyzdžių čia ):

26 авг. nustatė JohnJohnGa 26 rug . 2011-08-26 11:46 '11, 11:46, 2011-08-26 11:46
@ 10 atsakymų

Jei jį padalijame, netvarka yra:

 ++[[]][+[]] + [+[]] 

„JavaScript“ yra tiesa, kad +[] === 0 . + konvertuoja kažką į skaičių, tokiu atveju jis sumažės iki +"" arba 0 (žr. išsamią informaciją žemiau).

Taigi galime supaprastinti ( ++ turi nuspėjamumą per + ):

 ++[[]][0] + [0] 

Kadangi [[]][0] reiškia: gauti pirmąjį elementą iš [[]] , tiesa, kad:

  • [[]][0] grąžina vidinę masyvą ( [] ). Dėl nuorodų yra neteisinga pasakyti [[]][0] === [] , bet leisti vidinei matricai A išvengti klaidingo žymėjimo.
  • ++[[]][0] == A + 1 , nes ++ reiškia "prieaugį vienu".
  • ++[[]][0] === +(A + 1) ; kitaip tariant, jis visada bus numeris ( +1 nebūtinai grąžina skaičių, o ++ visada - dėka Tim Down už tai).

Vėlgi, mes galime supaprastinti netvarką į kažką labiau įskaitomą. Pakeiskite [] atgal į A :

 +([] + 1) + [0] 

„JavaScript“ tai taip pat tiesa: [] + 1 === "1" , nes [] == "" (tuščios matricos sąjunga), todėl:

  • +([] + 1) === +("" + 1) ir
  • +("" + 1) === +("1") ir
  • +("1") === 1

Leiskite dar labiau supaprastinti:

 1 + [0] 

Be to, tai pasakytina apie „JavaScript“: [0] == "0" , nes ji jungia masyvą su vienu elementu. Sąjunga sujungia simboliu atskirtus elementus. Vieno elemento pagalba jūs galite padaryti išvadą, kad ši logika padės pasiekti pirmąjį elementą.

Taigi, galų gale (skaičius + eilutė = eilutė):

 1 + "0" === "10" // Yay! 

+[] Specifikacijos duomenys:

Tai gana labirintas, bet, norint paleisti +[] , jis pirmą kartą konvertuojamas į eilutę, nes kas sako:

11.4.6 Unary + operatorius

Unary + operatorius savo operandą konvertuoja į numerio tipą.

Produktas UnaryExpression: + UnaryExpression įvertinamas taip:

  • Leiskite expr įvertinti UnaryExpression.

  • Grįžti į skaičių (GetValue (expr)).

ToNumber() sako:

Objektas

Taikykite šiuos veiksmus:

  • Leiskite primValue būti ToPrimitive (įvesties argumentas, užuomina eilutė).

  • Grąžina ToString (primValue).

ToPrimitive() sako:

Objektas

Grąžina numatytąją objekto reikšmę. Numatytoji objekto reikšmė gaunama skambinant į objekto vidinį [[DefaultValue]] metodą, suteikiant pasirinktinį „PreferredType“ užuominą. [[DefaultValue]] vidinio metodo elgesys šiame specifikacijoje apibrėžiamas visiems 8.12.8.

[[DefaultValue]] sako:

12/08/08 [[DefaultValue]] (užuomina)

Kai [[DefaultValue]] O vidinis metodas vadinamas pagalbos linija, imamasi šių veiksmų:

  • Leiskite „toString“ paskambinti O [[Get]] objekto vidinio metodo su argumentu „toString“ rezultatu.

  • Jei IsCallable (toString) yra teisinga, tada

a Leiskite str paskambinti į [[Call]] toString vidinį metodą, o O kaip šią vertę ir tuščią argumentų sąrašą.

b. Jei str yra primityvioji vertė, grįžkite str.

.toString masyvas sako:

15.4.4.2 Array.prototype.toString ()

Kai vadinamas „ToString“ metodas, atliekami šie veiksmai:

  • Leiskite masyvui paskambinti ToObject šiai vertei.

  • Leiskite funk yra paskambinti [[Get]] vidiniu masyvo metodu su argumentu „prisijungti“.

  • Jei „IsCallable“ (func) yra klaidinga, leiskite funkcija būti standartiniu „Object.prototype.toString“ metodu (15.2.4.2).

  • Grąžina vidinio metodo funkciją, kuri suteikia [[Call]] metodą, kaip šią vertę, ir tuščių argumentų sąrašą.

Taigi +[] nusileidžia į +"" nes [].join() === "" .

Vėlgi, + yra apibrėžiamas kaip:

11.4.6 Unary + operatorius

Unary + operatorius savo operandą konvertuoja į numerio tipą.

Produktas UnaryExpression: + UnaryExpression įvertinamas taip:

  • Leiskite expr įvertinti UnaryExpression.

  • Grįžti į skaičių (GetValue (expr)).

ToNumber nustatytas "" kaip:

MV StringNumericLiteral: [tuščias] yra 0.

Taigi +"" === 0 , taigi +[] === 0 .

1939 m
26 авг. atsakymas duotas pimvdb 26 rug . 2011-08-26 11:56 '11, 11:56, 2011-08-26 11:56
 ++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1 [+[]] => [0] 

Tada mes turime styginių sutapimą

border=0
 1+[0].toString() = 10 
109
26 авг. atsakymas pateikiamas Shef 26 rug. 2011-08-26 11:58 '11, 11:58, 2011-08-26 11:58

Toliau pateikiamas tinklaraščio įrašo pritaikymas, atsakant į šį klausimą, kurį paskelbiau, kol šis klausimas vis dar uždarytas. Nuorodos („HTML“) yra „ECMAScript 3“ specifikacijos kopija, vis dar pagrindinės „JavaScript“ šiuolaikinėse plačiai naudojamose žiniatinklio naršyklėse.

Pirma, komentaras: ši išraiška niekada nebus rodoma jokioje (sveikoje) gamybos aplinkoje ir bus naudojama tik kaip pratimas, kaip skaitytojas žino nešvarius „JavaScript“ kraštus. Pagrindinis principas yra tai, kad „JavaScript“ operatoriai, netiesiogiai konvertuojantys tarp tipų, yra naudingi, taip pat kai kurie bendrieji konversijos, tačiau daugelis detalių šiuo atveju nėra.

Išraiška ++[[]][+[]]+[+[]] iš pradžių gali atrodyti gana įspūdinga ir neaiški, tačiau iš tikrųjų yra gana lengva įsilaužti į atskiras išraiškas. Žemiau Ive tiesiog pridėjome skliaustelius dėl aiškumo; Galiu jus patikinti, kad jie nieko nekeičia, bet, jei norite patikrinti, ar tada nedvejodami perskaitykite apie grupės operatorių . Taigi išraiška gali būti aiškiau parašyta kaip

 ( ++[[]][+[]] ) + ( [+[]] ) 

Sunaikindami galime supaprastinti, pastebėdami, kad +[] yra įvertintas kaip 0 . Norėdami pamatyti, kodėl taip yra, patikrinkite unary + operatorių ir sekite šiek tiek apvyniojimo kelią, kuris baigiasi „ ToPrimitive “ tuščios matricos konvertavimu į tuščią eilutę, kuri tada pagaliau konvertuojama į 0 naudojant „ ToNumber“ . Dabar galime pakeisti 0 kiekvienu atveju +[] :

 ( ++[[]][0] ) + [0] 

Jau lengviau. Kalbant apie ++[[]][0] , tai yra prefiksų žingsnių ( ++ ), literatūros matricos, masyvo su vienu elementu, kuris pats yra tuščias masyvas ( [[]] ) ir priedų savybių ( [0] ) vadinamas masyvu, apibrėžtu matricos matrica.

Taigi, mes galime supaprastinti [[]][0] tik [] ir turime ++[] , tiesa? Tiesą sakant, taip nėra, nes ++[] vertinimas sukelia klaidą, kuri gali atrodyti paini. Tačiau šiek tiek galvojama apie „ ++ “ pobūdį tai aiškiai parodo: jis naudojamas kintamojo (pvz., ++i ) arba objekto savybių ++obj.count (pvz., ++obj.count ). Ji ne tik vertina vertę, bet ir išsaugo šią vertę kažkur. ++[] jis neturi jokios naujos vertės (nesvarbu, kokia ji būtų), nes nėra jokios nuorodos į atnaujinamą turtą ar objekto kintamąjį. Specifikacijose tai taikoma vidaus „ PutValue“ operacijai, kurią vadina prefikso prieaugio operatorius.

Taigi, ką daro ++[[]][0] ? Na, pagal panašią logiką, pvz., +[] , Vidinė masyvas konvertuojamas į 0 , ir ši vertė padidinama 1 , kad galėtume suteikti galutinę vertę 1 . Turto 0 reikšmė išorinėje matricoje yra atnaujinama iki 1 , o visa išraiška vertinama kaip 1 .

Tai palieka mus

 1 + [0] 

..., kuris yra paprastas pridėjimo pareiškimo naudojimas. Abu operandai pirmiausia paverčiami primityviais , o jei primityvioji reikšmė yra eilutė, atliekama styginių susiejimas, priešingu atveju atliekamas skaitmeninis papildymas. [0] paverčiamas į "0" , todėl naudojama styginių susiejimas, sukuriant "10" .

Kaip galutinis dalykas, kas iš karto neatsiranda, yra tai, kad vienas iš „ valueOf() Array.prototype toString() arba valueOf() pakeis išraiškos rezultatą, nes abu yra tikrinami ir naudojami, jei jie yra, kai objektas yra konvertuojamas į primityvi reikšmė. Pavyzdžiui, taip

 Array.prototype.toString = function() { return "foo"; }; ++[[]][+[]]+[+[]] 

... gamina "NaNfoo" . Kodėl taip atsitinka kaip skaitytojo pratybos ...

58
14 сент. Atsakymą pateikė Tim Down 14 Sep. 2011-09-14 16:54 '11 at 16:54 2011-09-14 16:54

Leidžia padaryti paprastą:

 ++[[]][+[]]+[+[]] = "10" var a = [[]][+[]]; var b = [+[]]; // so a == [] and b == [0] ++a; // then a == 1 and b is still that array [0] // when you sum the var a and an array, it will sum b as a string just like that: 1 + "0" = "10" 
21
30 дек. atsakymas duotas renatoluna gruodžio 30 d. 2011-12-30 18:41 '12, 18:41, 2011-12-30 18:41

Šis rezultatas vertinamas taip pat, bet šiek tiek mažiau.

 +!![]+''+(+[]) 
  • [] - konvertuoja masyvą, kuris yra konvertuojamas į 0, kai pridėsite ar atimant iš jo, todėl + [] = 0
  • ! [] - vertinamas kaip klaidingas, todėl iš čia. [] įvertintas kaip teisingas
  • + !! [] - konvertuoja tikrąją reikšmę į skaitinę vertę, kuri apskaičiuojama kaip teisinga, todėl šiuo atveju 1
  • + '' - prideda tuščią eilutę į išraišką, todėl skaičius bus konvertuojamas į eilutę
  • + [] - apskaičiuota kaip 0

todėl jis apskaičiuojamas

 +(true) + '' + (0) 1 + '' + 0 "10" 

Taigi dabar jūs turite tai, pabandykite:

 _=$=+[],++_+''+$ 
13
29 дек. Atsakymą pateikė Vladas Shlosbergas 29 d. 2011-12-29 02:13 „12, 12:13, 2011-12-29 02:13

+ [] yra vertinamas kaip 0 [...], o tada apibendrinant (+ operacija), masyvo turinys paverčiamas į eilutės reprezentaciją, sudarytą iš kableliais atskirtų elementų.

Bet kas, pavyzdžiui, masyvo indekso (turinčio didesnį prioritetą nei + operacija), yra eilinis ir nieko įdomus.

7
26 авг. atsakymas duotas Eskat0n 26 rug . 2011-08-26 11:58 '11, 11:58, 2011-08-26 11:58

Galbūt trumpiausi būdai, kaip įvertinti skaičių „10“ be numerių:

+!+[] + [+[]] // "10"

-~[] + [+[]] // "10"

// ========== Paaiškinimas ========== \ t

+!+[] : +[] Konvertuoja į 0. !0 konvertuoja į true . +true konvertuoja į 1. -~[] = -(-1) , kuris yra 1

[+[]] : +[] Konvertuoja į 0. [0] yra masyvas su vienu elementu 0.

Tada JS įvertina išraišką 1 + [0] , taigi Number + Array . Tada įvykdoma ECMA specifikacija: + operatorius paverčia abu operandus į eilutę, skambindamas į funkciją „ toString()/valueOf()Object prototipo. Jis veikia kaip priedų funkcija, jei abu išraiška yra skaičiai. Apgaulė yra ta, kad masyvai lengvai konvertuoja savo elementus į susietą eilutę.

Keletas pavyzdžių:

 1 + {} // "1[object Object]" 1 + [] // "1" 1 + new Date() // "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)" 

Gera išimtis yra ta, kad du Objects papildymai sukuria NaN :

 [] + [] // "" [1] + [2] // "12" {} + {} // NaN {a:1} + {b:2} // NaN [1, {}] + [2, {}] // "1,[object Object]2,[object Object]" 
4
19 июня '13 в 11:19 2013-06-19 11:19 atsakymą pateikė „ Arman McHitarian “ birželio 13 d., 11:19, 2013-06-19 11:19
  • Unary plius nurodyta eilutė konvertuojama į skaičių
  • Šios eilutės operatorius padidina ir padidina 1
  • [] == ''. Tuščia linija
  • + '' arba + [] tarifai 0.

     ++[[]][+[]]+[+[]] = 10 ++[''][0] + [0] : First part is gives zeroth element of the array which is empty string 1+0 10 
1
30 дек. Atsakymas suteikiamas Praveen Vedanth, gruodžio 30 d. 2011-12-30 11:10 '12, 11:10, 2011-12-30 11:10

Žingsnis po žingsnio + pasukite vertę į skaičių, o jei į tuščią masyvą pridėsite +[] , nes jis yra tuščias ir lygus 0 , jis bus

Taigi, iš ten dabar pažiūrėkite į savo kodą, tai yra ++[[]][+[]]+[+[]] ...

Ir tarp jų yra plius ++[[]][+[]] + [+[]]

Taigi, šie [+[]] grįš [0] nes jie turi tuščią masyvą, kuris konvertuojamas į 0 viduje kitoje matricoje ...

Taigi įsivaizduokite, kad pirmoji vertė yra dviejų matmenų masyvas su viena masyvo dalimi ... taip, kad [[]][+[]] bus lygi [[]][0] kuri sugrįš [] ...

Ir pabaigoje ++ konvertuokite jį ir padidinkite iki 1 ...

Taigi galite įsivaizduoti, 1 + "0" bus "10" ...

2019

19 янв. Atsakymą Alireza pateikė sausio 19 d. 2019-01-19 03:32 '19 , 3:32 2019-01-19 03:32

Pažvelkite į JSFuck kompiliatorių ir čia yra visas išėjimas .

0
22 янв. Atsakymą pateikė Kamil Kiełczewski sausio 22 d. 2019-01-22 01:28 '19 - 1:28 2019-01-22 01:28

Kiti klausimai dėl etikečių arba Užduoti klausimą