මෙය වලංගු වන "10"
අතර ජාවාස්ක්රිප්ට් හි ඇති නූල නැවත ලබා දෙයි ( තවත් උදාහරණ මෙහි ):
console.log(++[[]][+[]]+[+[]])
මන්ද? මෙහි සිදුවන්නේ කුමක්ද?
මෙය වලංගු වන "10"
අතර ජාවාස්ක්රිප්ට් හි ඇති නූල නැවත ලබා දෙයි ( තවත් උදාහරණ මෙහි ):
console.log(++[[]][+[]]+[+[]])
මන්ද? මෙහි සිදුවන්නේ කුමක්ද?
Answers:
අපි එය බෙදුවහොත්, අවුල සමාන වේ:
++[[]][+[]]
+
[+[]]
JavaScript හි එය සත්යයකි +[] === 0
. +
යමක් අංකයක් බවට පරිවර්තනය කරයි, මේ අවස්ථාවේ දී එය පහළට +""
හෝ 0
(පහත පිරිවිතර විස්තර බලන්න).
එමනිසා, අපට එය සරල කළ හැකිය ( ++
ඊට වඩා ප්රමුඛත්වයක් ඇත +
):
++[[]][0]
+
[0]
මක්නිසාද යත් [[]][0]
: පළමු අංගය ලබා ගන්න [[]]
, එය සත්යයකි:
[[]][0]
අභ්යන්තර අරාව ( []
) ලබා දෙයි. යොමු කිරීම් නිසා එය පැවසීම වැරදිය [[]][0] === []
, නමුත් A
වැරදි අංකනය වළක්වා ගැනීම සඳහා අභ්යන්තර අරාව අමතමු.
++
එහි ක්රියාකාරිත්වයට පෙර “එකකින් වැඩි කිරීම සහ වැඩි කළ ප්රති result ලය ලබා දීම” යන්නයි. ඒ නිසා ++[[]][0]
සමාන වේ Number(A) + 1
(හෝ +A + 1
).
නැවතත්, අපට අවුල වඩාත් පැහැදිලි දෙයකට සරල කළ හැකිය. අපි []
නැවත ආදේශ කරමු A
:
(+[] + 1)
+
[0]
+[]
අරාව අංකයට බල කිරීමට පෙර 0
, එය පළමුව නූලකට බල කළ යුතුය, එනම් ""
නැවත. අවසාන වශයෙන්, 1
එකතු කරනු ලැබේ, එහි ප්රති results ලය වනු ඇත 1
.
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
අපි එය තවත් සරල කරමු:
1
+
[0]
එසේම, මෙය ජාවාස්ක්රිප්ට් හි සත්ය වේ: [0] == "0"
මන්ද, එය එක් මූලද්රව්යයක් සමඟ අරාවකට සම්බන්ධ වන බැවිනි. සම්බන්ධ වීමෙන් වෙන් කරන ලද මූලද්රව්යයන් සංයුක්ත වේ ,
. එක් මූලද්රව්යයක් සමඟ, මෙම තර්කනය ප්රථම මූලද්රව්යයේම ප්රති result ලය වනු ඇතැයි ඔබට අනුමාන කළ හැකිය.
මෙම අවස්ථාවේදී, මෙහෙයුම් +
දෙකක් දකී: අංකයක් සහ අරාවක්. එය දැන් උත්සාහ කරන්නේ දෙදෙනා එකම වර්ගයට බල කිරීමට ය. පළමුවෙන්ම, අරාව නූලට බල කෙරෙයි "0"
, ඊළඟට, අංකය ( "1"
) ලෙස බල කෙරේ. අංක +
නූල් ===
නූල් .
"1" + "0" === "10" // Yay!
පිරිවිතර විස්තර සඳහා +[]
:
මෙය තරමක් ප්රහේලිකාවකි, නමුත් එසේ කිරීමට නම් +[]
, පළමුව එය නූලකට පරිවර්තනය වේ +
.
11.4.6 Unary + Operator
ඒකීය + ක්රියාකරු එහි ක්රියාකාරිත්වය අංක වර්ගයට පරිවර්තනය කරයි.
නිෂ්පාදනය UnaryExpression: + UnaryExpression පහත පරිදි ඇගයීමට ලක් කෙරේ:
UnaryExpression තක්සේරු කිරීමේ ප්රති result ලයක් ලෙස expr කරමු.
ToNumber (GetValue (expr)) වෙත ආපසු යන්න.
ToNumber()
පවසයි:
වස්තුව
පහත පියවර අනුගමනය කරන්න:
PrimValue ToPrimitive (ආදාන තර්කය, ඉඟි නූල්) වීමට ඉඩ දෙන්න.
ToString (primValue) වෙත ආපසු යන්න.
ToPrimitive()
පවසයි:
වස්තුව
වස්තුව සඳහා පෙරනිමි අගයක් ලබා දෙන්න. වස්තුවක පෙරනිමි අගය ලබා ගන්නේ වස්තුවෙහි [[DefaultValue]] අභ්යන්තර ක්රමය ඇමතීමෙන්, විකල්ප ඉඟිය මනාප ටයිප් පසුකරමිනි. [[DefaultValue]] අභ්යන්තර ක්රමයේ හැසිරීම 8.12.8 හි ඇති සියලුම දේශීය ECMAScript වස්තු සඳහා මෙම පිරිවිතරයෙන් අර්ථ දක්වා ඇත.
[[DefaultValue]]
පවසයි:
8.12.8 [[DefaultValue]] (ඉඟිය)
O හි [[DefaultValue]] අභ්යන්තර ක්රමය ඉඟි නූල් සමඟ හැඳින්වූ විට, පහත පියවර ගනු ලැබේ:
වස්තුව O හි [[Get]] අභ්යන්තර ක්රමය "toString" තර්කය සමඟ ඇමතීමේ ප්රති to ලය toString වේ.
IsCallable (toString) සත්ය නම්,
ඒ. [මෙම ඇමතුම] ටෝස්ට්රිං හි අභ්යන්තර ක්රමය ඇමතීමේ ප්රති result ලය වීමට ඉඩ දෙන්න, ඕ සමඟ මෙම අගය සහ හිස් තර්ක ලැයිස්තුවක් ඇත.
බී. Str යනු ප්රාථමික අගයක් නම්, str වෙත ආපසු යන්න.
මෙම .toString
රැසක් මෙසේ පවසයි:
15.4.4.2 Array.prototype.toString ()
ToString ක්රමය හැඳින්වූ විට, පහත පියවර ගනු ලැබේ:
මෙම අගය මත ToObject ඇමතීමේ ප්රති result ලය අරාව වේ.
[[ලබා ගන්න]] අරාවෙහි අභ්යන්තර ක්රමය "එක්වන්න" යනුවෙන් හැඳින්වීමේ ප්රති result ලයක් ලෙස විනෝද වීමට ඉඩ දෙන්න.
IsCallable (func) අසත්ය නම්, func යනු සම්මත බිල්ට් ක්රමය වන Object.prototype.toString (15.2.4.2) වේ.
මෙම අගය සහ හිස් තර්ක ලැයිස්තුවක් ලෙස අරාව සපයන [[අමතන්න]] විනෝද ක්රමයේ අභ්යන්තර ක්රමය ඇමතීමේ ප්රති result ලය ලබා දෙන්න.
ඒ නිසා +[]
වෙත පැමිණේ +""
නිසා [].join() === ""
.
නැවතත්, පහත පරිදි +
අර්ථ දැක්වේ:
11.4.6 Unary + Operator
ඒකීය + ක්රියාකරු එහි ක්රියාකාරිත්වය අංක වර්ගයට පරිවර්තනය කරයි.
නිෂ්පාදනය UnaryExpression: + UnaryExpression පහත පරිදි ඇගයීමට ලක් කෙරේ:
UnaryExpression තක්සේරු කිරීමේ ප්රති result ලයක් ලෙස expr කරමු.
ToNumber (GetValue (expr)) වෙත ආපසු යන්න.
ToNumber
පහත පරිදි අර්ථ දක්වා ""
ඇත:
StringNumericLiteral හි MV ::: [හිස්] 0 වේ.
ඉතින් +"" === 0
, මේ අනුව +[] === 0
.
true
එන්නේ වටිනාකම සහ වර්ගය යන දෙකම එක හා සමාන නම් පමණි. 0 == ""
ප්රතිලාභ true
(වර්ගය බවට පත් වූ පසු එම), නමුත් 0 === ""
වේ false
(එම වර්ග නැත).
1 + [0]
නොව "1" + [0]
, උපසර්ගය (මන්ද ++
) ක්රියාකරු හැම විටම අංකය පැමිණේ. Bclary.com/2004/11/07/#a-11.4.4
++[[]][0]
ඇත්ත වශයෙන්ම ආපසු එයි 1
, නමුත් ++[]
දෝෂයක් විසි කරයි. මෙය විශිෂ්ටයි, මන්ද එය ++[[]][0]
පහළට තම්බන බවක් පෙනේ ++[]
. එසේ ++[]
නොවුවද වැරැද්දක් ++[[]][0]
කරන්නේ මන්දැයි ඔබට යම් අදහසක් තිබේද?
PutValue
උපසර්ග මෙහෙයුමේ (ES3 පාරිභාෂිතයේ, 8.7.2) ඇමතුම තුළ ගැටලුව ඇති බව මට හොඳටම විශ්වාසයි . PutValue
යොමු කිරීමක් අවශ්ය වන අතර []
එය තනිවම ප්රකාශනයක් ලෙස යොමු කිරීමක් නොකරයි. විචල්ය සඳහනක් (අපි කලින් අර්ථ කියලා කියන්න අඩංගු ප්රකාශනයක් var a = []
පසුව ++a
ක්රියා කරයි) හෝ වස්තුවක දේපල ප්රවේශ (වැනි [[]][0]
යොමු නිෂ්පාදනය). සරලව කිවහොත්, උපසර්ග ක්රියාකරු විසින් වටිනාකමක් නිපදවනවා පමණක් නොව, එම අගය තැබීමට කොතැනක හෝ අවශ්ය වේ.
var a = []; ++a
, a
1. ක්රියාත්මක කිරීමෙන් පසු වේ ++[[]][0]
, විසින් නිර්මාණය කරන අරාව [[]]
ප්රකාශනය දැන් හුදෙක් 1 දර්ශකය 0 දී සංඛ්යාව අඩංගු වේ ++
මෙය කිරීමට යොමු අවශ්ය වේ.
++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]
එවිට අපට නූල් සම්මුතියක් ඇත
1+[0].toString() = 10
===
වඩා පැහැදිලි නොවේ ද =>
?
මෙම ප්රශ්නය තවමත් වසා තිබියදී මා පළ කළ මෙම ප්රශ්නයට පිළිතුරු සපයන බ්ලොග් සටහනකින් පහත දැක්වේ . අද දින බහුලව භාවිතා වන වෙබ් බ්රව්සර්වල ජාවාස්ක්රිප්ට් සඳහා මූලික පදනම වන ඊසීඑම්එස්ක්රිප්ට් 3 පිරිවිතරයට සබැඳි (HTML පිටපතක්) වේ.
පළමුවෙන්ම, අදහස් දැක්වීමක්: මේ ආකාරයේ ප්රකාශනය කිසි විටෙකත් කිසිදු (බුද්ධිමත්) නිෂ්පාදන පරිසරයක් තුළ නොපෙන්වන අතර එය ජාවාස්ක්රිප්ට්හි අපිරිසිදු දාර පා the කයා කොතරම් හොඳින් දනීද යන්න පිළිබඳ අභ්යාසයක් ලෙස පමණක් ප්රයෝජනවත් නොවේ. ජාවාස්ක්රිප්ට් ක්රියාකරුවන් වර්ග අතර ව්යංගයෙන් පරිවර්තනය කරන පොදු මූලධර්මය සමහර පොදු පරිවර්තනයන් මෙන් ප්රයෝජනවත් වේ, නමුත් මෙම නඩුවේ බොහෝ විස්තර එසේ නොවේ.
මෙම ප්රකාශනය ++[[]][+[]]+[+[]]
මුලින් තරමක් බලගතු හා අපැහැදිලි ලෙස පෙනෙන්නට තිබුණද ඇත්ත වශයෙන්ම එය වෙනම ප්රකාශන බවට බිඳ දැමීම සාපේක්ෂව පහසුය. පහතින් මම පැහැදිලි කිරීම සඳහා වරහන් එකතු කර ඇත; ඔවුන් කිසිවක් වෙනස් නොකරන බව මට සහතික විය හැකිය, නමුත් ඔබට එය සත්යාපනය කිරීමට අවශ්ය නම් කණ්ඩායම් ක්රියාකරු ගැන කියවීමට නිදහස් වන්න . එබැවින් ප්රකාශනය වඩාත් පැහැදිලිව ලිවිය හැකිය
( ++[[]][+[]] ) + ( [+[]] )
මෙය බිඳ දැමීම, +[]
ඇගයීම නිරීක්ෂණය කිරීමෙන් අපට සරල කළ හැකිය 0
. මෙය සත්ය වන්නේ මන්දැයි ඔබම තෘප්තිමත් කර ගැනීම සඳහා, ඒකීය + ක්රියාකරු පරීක්ෂා කර ToPrimitive හිස් අරාව හිස් නූලක් බවට පරිවර්තනය කිරීමත් සමඟ අවසන් වන තරමක් ව්යාකූල මාවත අනුගමනය කරන්න , එය අවසානයේ ToNumber0
විසින් පරිවර්තනය කරනු ලැබේ . අපට දැන් 0
එක් එක් අවස්ථාව වෙනුවට ආදේශ කළ හැකිය +[]
:
( ++[[]][0] ) + [0]
දැනටමත් සරලයි. සඳහා පරිදි ++[[]][0]
, සංයෝග බව, උපසර්ගය වර්ධකයක් ක්රියාකරු ( ++
) සඳහා ප්රායෝගික මාලාවක් ම හිස් අරා (බව තනි අංගයක් සමග මාලාවක් අර්ථ [[]]
) සහ දේපල accessor ( [0]
අරාව ප්රායෝගික මගින් අර්ථ අරාවක් මත හැඳින්වේ).
ඉතින්, අපට [[]][0]
යුක්තිසහගත ලෙස සරල කළ හැකි []
අතර අපට තිබේ ++[]
, නේද? ඇත්ත වශයෙන්ම, මෙය එසේ නොවේ, මන්ද ඇගයීම ++[]
දෝෂයක් ඇති කරයි, එය මුලින් ව්යාකූල බවක් පෙනෙන්නට තිබේ. කෙසේ වෙතත්, ස්වභාවය පිළිබඳ මඳක් සිතා බැලීමෙන් ++
මෙය පැහැදිලි වේ: එය විචල්යයක් (උදා ++i
) හෝ වස්තු දේපලක් (උදා ++obj.count
) වැඩි කිරීමට භාවිතා කරයි. එය අගයකට තක්සේරු කරනවා පමණක් නොව, එම අගය කොතැනක හෝ ගබඩා කරයි. කෙසේ වෙතත් ++[]
, නව අගය (එය කුමක් වුවත්) තැබීමට එය කොතැනකවත් නැත, මන්ද වස්තු දේපල හෝ යාවත්කාලීන කිරීම සඳහා විචල්යයක් ගැන සඳහනක් නොමැති බැවිනි. පිරිවිතරයන්ට අනුව, මෙය අභ්යන්තර පුට්වාලූ මෙහෙයුමෙන් ආවරණය වන අතර එය උපසර්ග වර්ධක ක්රියාකරු විසින් හැඳින්වේ.
ඉතින්, කුමක් කරන්නේද ++[[]][0]
? හොඳයි, සමාන තර්කනයකින් +[]
, අභ්යන්තර අරාව බවට පරිවර්තනය වන 0
අතර මෙම අගය 1
අපට අවසාන අගයක් ලබා දීමෙන් වැඩි කරයි 1
. 0
පිටත අරාවෙහි ඇති දේපලවල වටිනාකම යාවත්කාලීන වන 1
අතර සමස්ත ප්රකාශනය ඇගයීමට ලක් කරයි 1
.
මෙය අප අතහැර යයි
1 + [0]
... එය එකතු කිරීමේ ක්රියාකරුගේ සරල භාවිතයකි . ඔපෙරන්ඩ් දෙකම මුලින්ම ප්රාථමික බවට පරිවර්තනය වන අතර, ප්රාථමික අගය නූලක් නම්, නූල් සංයුක්ත කිරීම සිදු කරයි, එසේ නොමැති නම් සංඛ්යාත්මක එකතු කිරීමක් සිදු කරයි. [0]
බවට පරිවර්තනය වේ "0"
, එබැවින් නිෂ්පාදනය කිරීම සඳහා නූල් සමෝච්ඡය භාවිතා "10"
වේ.
අවසාන පැත්තක් ලෙස, ක්ෂණිකව නොපෙනෙන දෙයක් නම්, එක් ක්රමයක් toString()
හෝ valueOf()
ක්රමයක් ඉක්මවා යාම Array.prototype
ප්රකාශනයේ ප්රති result ලය වෙනස් කරනු ඇත, මන්ද යත් දෙකම පරීක්ෂා කර වස්තුවක් ප්රාථමික අගයක් බවට පරිවර්තනය කිරීමේදී තිබේ නම් ඒවා භාවිතා කර ඇති බැවිනි. උදාහරණයක් ලෙස, පහත සඳහන් දෑ
Array.prototype.toString = function() {
return "foo";
};
++[[]][+[]]+[+[]]
... නිෂ්පාදනය කරයි "NaNfoo"
. මෙය සිදුවීමට හේතුව පා er කයාට අභ්යාසයක් ලෙස ඉතිරිව ඇත ...
එය සරල කරමු:
++[[]][+[]]+[+[]] = "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"
මෙය තක්සේරු කරන්නේ එකම නමුත් ටිකක් කුඩා ය
+!![]+''+(+[])
එසේ ඇගයීමට ලක් කරයි
+(true) + '' + (0)
1 + '' + 0
"10"
දැන් ඔබට එය ලැබුණා, මෙය උත්සාහ කරන්න:
_=$=+[],++_+''+$
"10"
+ [] 0 ලෙස ඇගයීමට ලක් කරයි [...] ඉන්පසු එය ඕනෑම දෙයක් සමඟ සාරාංශ කිරීම (+ ක්රියාකාරිත්වය) අරා අන්තර්ගතය කොමා සමඟ සම්බන්ධ වූ මූලද්රව්යයන්ගෙන් සමන්විත එහි නූල් නිරූපණයට පරිවර්තනය කරයි.
අරාවෙහි දර්ශකය ගැනීම වැනි වෙනත් ඕනෑම දෙයක් (+ ක්රියාකාරිත්වයට වඩා ප්රමුඛතාවයක් ඇත) සාමාන්ය දෙයක් වන අතර එය සිත්ගන්නා සුළු දෙයක් නොවේ.
ඉලක්කම් නොමැතිව ප්රකාශනයක් "10" ලෙස තක්සේරු කිරීමට ඇති කෙටිම ක්රම සමහර විට:
+!+[] + [+[]]
// "10"
-~[] + [+[]]
// "10"
// ========== පැහැදිලි කිරීම ========= \\
+!+[]
: +[]
0 !0
බවට පරිවර්තනය කරයි true
. +true
1. ආගමට හරවා ගැනීම
-~[]
= -(-1)
1 වන
[+[]]
: +[]
0 [0]
බවට පරිවර්තනය කිරීම තනි මූලද්රව්යය 0 සහිත අරාවකි.
එවිට JS මෙම ඇගයීමට ලක් 1 + [0]
, මේ අනුව, Number + Array
අදහස් ප්රකාශ. එවිට ECMA පිරිවිතරයන් ක්රියාත්මක වේ: +
ක්රියාකරු විසින් toString()/valueOf()
මූලික Object
මූලාකෘතියෙන් ශ්රිත ඇමතීමෙන් ඔපෙරන්ඩ් දෙකම නූලකට පරිවර්තනය කරයි . ප්රකාශනයක ක්රියාකාරිත්වය දෙකම සංඛ්යා පමණක් නම් එය ආකලන ශ්රිතයක් ලෙස ක්රියාත්මක වේ. උපක්රමය නම්, අරා පහසුවෙන් ඒවායේ මූලද්රව්ය සංයුක්ත නූල් නිරූපණයක් බවට පරිවර්තනය කිරීමයි.
උදාහරණ කිහිපයක්:
1 + {} // "1[object Object]"
1 + [] // "1"
1 + new Date() // "1Wed Jun 19 2013 12:13:25 GMT+0400 (Caucasus Standard Time)"
Objects
එකතු කිරීම් දෙකක් නිසා හොඳ ව්යතිරේකයක් ඇත NaN
:
[] + [] // ""
[1] + [2] // "12"
{} + {} // NaN
{a:1} + {b:2} // NaN
[1, {}] + [2, {}] // "1,[object Object]2,[object Object]"
+ '' හෝ + [] 0 තක්සේරු කරයි.
++[[]][+[]]+[+[]] = 10
++[''][0] + [0] : First part is gives zeroth element of the array which is empty string
1+0
10
[]
ය නොවන සමාන ""
. පළමුව මූලද්රව්යය නිස්සාරණය කර, පසුව පරිවර්තනය කරනු ලැබේ ++
.
එහි පියවරෙන් පියවර, +
අගය අංකයකට හරවන්න , ඔබ හිස් අරාවකට එකතු කළහොත් +[]
... එය හිස් හා සමාන බැවින් 0
එය සිදුවනු ඇත
එතැන් සිට, දැන් ඔබේ කේතය සොයා බලන්න, එය ++[[]][+[]]+[+[]]
...
ඔවුන් අතර ++[[]][+[]]
+ ප්ලස් ඇත[+[]]
හිස් අරා එකක් ඇති බැවින් මේවා [+[]]
නැවත පැමිණෙනු ඇත, එය අනෙක් අරාව තුළට [0]
පරිවර්තනය 0
වේ ...
ඉතින් සිතූ පරිදි, පළමු අගය ද්විමාන අරාව ඇතුළත එක් අරාවක් ඇත ... එබැවින් නැවත පැමිණීමට [[]][+[]]
සමාන වේ ...[[]][0]
[]
අවසානයේ ++
එය පරිවර්තනය කර එය වැඩි කරන්න 1
...
ඉතින් ඔබට හිතාගන්න පුළුවන්, 1
+ "0"
වේවි "10"
...
+[]
හිස් අරාවක් ඇති බව තේරුම් ගැනීමෙන් ආරම්භ කරන්න0
... පසුව දහවල් නාස්ති කරන්න ...;)