এটি বৈধ এবং "10"
জাভাস্ক্রিপ্টে স্ট্রিংটি দেয় ( আরও উদাহরণ এখানে ):
console.log(++[[]][+[]]+[+[]])
কেন? এখানে কি হচ্ছে?
এটি বৈধ এবং "10"
জাভাস্ক্রিপ্টে স্ট্রিংটি দেয় ( আরও উদাহরণ এখানে ):
console.log(++[[]][+[]]+[+[]])
কেন? এখানে কি হচ্ছে?
উত্তর:
আমরা যদি এটি বিভক্ত করি, গণ্ডগোলের সমান:
++[[]][+[]]
+
[+[]]
জাভাস্ক্রিপ্টে, এটি সত্য +[] === 0
। +
কোনও কিছুকে একটি সংখ্যায় রূপান্তর করে এবং এক্ষেত্রে এটি নেমে আসবে +""
বা 0
(নীচে বিশদ বিবরণ দেখুন)।
অতএব, আমরা এটিকে সহজ করতে পারি ( ++
এর চেয়ে বেশি প্রাধান্য রয়েছে +
):
++[[]][0]
+
[0]
কারণটির [[]][0]
অর্থ: প্রথম উপাদানটি থেকে পাওয়া [[]]
, এটি সত্য যে:
[[]][0]
অভ্যন্তরীণ অ্যারে ( []
) প্রদান করে। রেফারেন্সের কারণে এটি বলা ভুল [[]][0] === []
, তবে আসল ভুলটি A
এড়াতে অভ্যন্তরীণ অ্যারেটি কল করি ।
++
এর অপারেন্ডের অর্থ "এক এক করে বৃদ্ধি এবং বর্ধিত ফলাফলটি ফিরে আসা" এর আগে। সুতরাং ++[[]][0]
সমতুল্য হয় Number(A) + 1
(অথবা +A + 1
)।
আবার, আমরা এই জগাখিচিকে আরও সুস্পষ্ট কিছুতে সহজ করতে পারি। এর জন্য বিকল্প []
ফিরে আসা যাক A
:
(+[] + 1)
+
[0]
+[]
সংখ্যায় অ্যারে জোর করার আগে 0
, এটি প্রথমে একটি স্ট্রিংয়ে জোর করা দরকার, যা ""
আবার। অবশেষে, 1
যোগ করা হয়, যার ফলস্বরূপ 1
।
(+[] + 1) === (+"" + 1)
(+"" + 1) === (0 + 1)
(0 + 1) === 1
আসুন এটি আরও সরল করুন:
1
+
[0]
এছাড়াও, এটি জাভাস্ক্রিপ্টে সত্য: [0] == "0"
কারণ এটি একটি উপাদানের সাথে অ্যারে যোগ দিচ্ছে। যোগদান করা দ্বারা পৃথক করা উপাদানগুলিকে একত্রিত করবে ,
। একটি উপাদান দিয়ে, আপনি অনুমান করতে পারেন যে এই যুক্তিটির ফলে প্রথম উপাদানটিই হবে।
এই ক্ষেত্রে, +
দুটি অপারেশন দেখুন: একটি সংখ্যা এবং একটি অ্যারে। এটি এখন দু'জনকে একই ধরণের উপর চাপিয়ে দেওয়ার চেষ্টা করছে। প্রথমে অ্যারেটি স্ট্রিংয়ে জোর করা হয়, তারপরে "0"
, সংখ্যাটি স্ট্রিং ( "1"
) এ জোর করা হয় । সংখ্যা +
স্ট্রিং ===
স্ট্রিং ।
"1" + "0" === "10" // Yay!
এর জন্য নির্দিষ্টকরণের বিশদ +[]
:
এটি বেশ গোলকধাঁধা, তবে করণীয় +[]
, প্রথমে এটি একটি স্ট্রিংয়ে রূপান্তরিত হচ্ছে কারণ এটি যা +
বলে:
১১.৪. Un ইউনারি + অপারেটর
অ্যানারি + অপারেটর তার অপারেন্ডকে সংখ্যা প্রকারে রূপান্তর করে।
উত্পাদন UnaryExpression: + UnaryExpression নিম্নলিখিত হিসাবে মূল্যায়ন করা হয়:
এক্সপ্রেসকে ইউনারিএক্সপ্রেসনের মূল্যায়নের ফলাফল হতে দিন।
ToNumber (গেটভ্যালু (এক্সপ্রেস)) ফিরুন।
ToNumber()
বলেছেন:
উদ্দেশ্য
নিম্নলিখিত পদক্ষেপগুলি প্রয়োগ করুন:
প্রাইমভ্যালুকে টোপ্রিমিটাইভ হতে দিন (ইনপুট আর্গুমেন্ট, ইঙ্গিতের স্ট্রিং)।
টুস্ট্রিং (প্রাইমভ্যালু) ফিরুন।
ToPrimitive()
বলেছেন:
উদ্দেশ্য
অবজেক্টের জন্য একটি ডিফল্ট মান ফিরিয়ে দিন। Objectচ্ছিক ইঙ্গিত PreferredType পেরিয়ে অবজেক্টের অভ্যন্তরীণ পদ্ধতিতে [[DefaultValue]] কল করে কোনও সামগ্রীর ডিফল্ট মান পুনরুদ্ধার করা হয়। [[DefaultValue]] অভ্যন্তরীণ পদ্ধতির আচরণটি 8.12.8 তে সমস্ত নেটিভ ECMAScript অবজেক্টের জন্য এই স্পেসিফিকেশন দ্বারা সংজ্ঞায়িত করা হয়।
[[DefaultValue]]
বলেছেন:
৮.১২.৮ [[ডিফল্ট মূল্য]] (ইঙ্গিত)
যখন [[DefaultValue]] হে এর অভ্যন্তরীণ পদ্ধতিটিকে ইঙ্গিত স্ট্রিং সহ ডাকা হয়, নিম্নলিখিত পদক্ষেপ নেওয়া হয়:
টুস্ট্রিংকে "[স্টেট]" অবজেক্ট ও এর অভ্যন্তরীণ পদ্ধতিটি "টু স্ট্রিং" দিয়ে কল করার ফলাফল হতে পারে।
যদি ইসক্লেলেবল (টু স্ট্রিং) সত্য হয় তবে,
ক। এই মান হিসাবে একটি খালি আর্গুমেন্ট তালিকা হিসাবে ও স্ট্রিংয়ের সাথে [[কল]] টো স্ট্রিংয়ের অভ্যন্তরীণ পদ্ধতি কল করার ফলাফল হোক।
খ। যদি str একটি আদিম মান হয় তবে স্ট্র্টটি ফেরত দিন।
.toString
একটি অ্যারের বলেছেন:
15.4.4.2 অ্যারে.প্রোটোটাইপ.টো স্ট্রিং ()
যখন টস্ট্রিং পদ্ধতিটি ডাকা হয়, নিম্নলিখিত পদক্ষেপ নেওয়া হয়:
অ্যারে এই মানটিতে ToObject কল করার ফলাফল হতে দিন।
আসুন "[যোগ করুন" যুক্তিযুক্ত অ্যারের অভ্যন্তরীণ পদ্ধতিটিকে [[get]] বলার ফলাফল হতে দিন fun
যদি ইসক্লেলেবল (ফানক) মিথ্যা হয়, তবে ফানকটি স্ট্যান্ডার্ড বিল্ট-ইন পদ্ধতি অবজেক্ট.প্রোটোটাইপ.টো স্ট্রিং (15.2.4.2) হতে দিন।
[[কল]] ফানকের অভ্যন্তরীণ পদ্ধতিটিকে এই মান এবং একটি খালি যুক্তি তালিকা হিসাবে অ্যারে সরবরাহ করার জন্য কল করার ফলাফলটি ফিরিয়ে দিন।
তাই +[]
নেমে আসে +""
, কারণ [].join() === ""
।
আবার, +
সংজ্ঞা দেওয়া হয়েছে:
১১.৪. Un ইউনারি + অপারেটর
অ্যানারি + অপারেটর তার অপারেন্ডকে সংখ্যা প্রকারে রূপান্তর করে।
উত্পাদন UnaryExpression: + UnaryExpression নিম্নলিখিত হিসাবে মূল্যায়ন করা হয়:
এক্সপ্রেসকে ইউনারিএক্সপ্রেসনের মূল্যায়নের ফলাফল হতে দিন।
ToNumber (গেটভ্যালু (এক্সপ্রেস)) ফিরুন।
ToNumber
হিসাবে সংজ্ঞায়িত করা ""
হয়:
স্ট্রিং নিউমেরিকাল লিটারাল এর এমভি ::: [খালি] 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
প্রিফিক্স অপারেশনে সমস্যাটি কল (ইএস 3 টার্মিনোলজিতে, ৮. is.২) এ রয়েছে তা আমি নিশ্চিত । PutValue
একটি রেফারেন্স প্রয়োজন যখন []
নিজের মতামত হিসাবে একটি রেফারেন্স উত্পাদন করে না। একটি ভেরিয়েবল রেফারেন্স সহ একটি অভিব্যক্তি (বলুন আমরা পূর্বে সংজ্ঞায়িত var a = []
হয়ে ++a
কাজ করব) বা কোনও সামগ্রীর সম্পত্তি অ্যাক্সেস (যেমন [[]][0]
) একটি রেফারেন্স তৈরি করে। সহজ কথায়, উপসর্গ অপারেটর কেবল একটি মান তৈরি করে না, সেই মানটি রাখার জন্য এটি কোথাও প্রয়োজন।
var a = []; ++a
, a
1 হয়। কার্যকর করার পরে ++[[]][0]
, [[]]
এক্সপ্রেশন দ্বারা তৈরি অ্যারে এখন সূচক 0 তে 1 নম্বর রয়েছে এটি করার ++
জন্য একটি রেফারেন্স প্রয়োজন requires
++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]
তারপরে আমাদের কাছে একটি স্ট্রিং কনটেটেশন রয়েছে
1+[0].toString() = 10
===
চেয়ে =>
কি স্পষ্ট হবে না ?
নীচে একটি ব্লগ পোস্ট থেকে এই প্রশ্নের উত্তর দেওয়া হয়েছিল যা এই পোস্টটি এখনও বন্ধ থাকা অবস্থায় আমি পোস্ট করেছি answ লিঙ্কগুলি ECMAScript 3 বৈশিষ্টের (একটি HTML অনুলিপি), আজও সাধারণভাবে ব্যবহৃত ওয়েব ব্রাউজারগুলিতে জাভাস্ক্রিপ্টের বেসলাইন।
প্রথমত, একটি মন্তব্য: এই ধরণের অভিব্যক্তিটি কখনই কোনও (বুদ্ধিমান) উত্পাদন পরিবেশে প্রদর্শিত হবে না এবং পাঠক জাভাস্ক্রিপ্টের নোংরা প্রান্তগুলি কতটা ভাল জানেন সে সম্পর্কে অনুশীলন হিসাবে এটি কোনওভাবেই ব্যবহারযোগ্য নয়। যে সাধারণ নীতিটি জাভাস্ক্রিপ্ট অপারেটরগুলি স্পষ্টভাবে প্রকারের মধ্যে রূপান্তরিত করে সেগুলি দরকারী, যেমন কিছু সাধারণ রূপান্তর রয়েছে তবে এই ক্ষেত্রে বিশদটির বেশিরভাগটি তা নয়।
অভিব্যক্তিটি ++[[]][+[]]+[+[]]
প্রথমে বরং আরোপিত এবং অস্পষ্ট মনে হতে পারে তবে এটি পৃথক প্রকাশে তুলনামূলকভাবে সহজ ভাঙ্গা। নীচে আমি স্পষ্টতার জন্য কেবল বন্ধনী যুক্ত করেছি; আমি আপনাকে আশ্বাস দিতে পারি তারা কোনও পরিবর্তন করেনি, তবে আপনি যদি তা যাচাই করতে চান তবে গ্রুপিং অপারেটরটি সম্পর্কে দ্বিধায় পড়ুন । সুতরাং, অভিব্যক্তি হিসাবে আরও পরিষ্কারভাবে লেখা যেতে পারে
( ++[[]][+[]] ) + ( [+[]] )
এই ভেঙ্গে, আমরা যে দেখে প্রক্রিয়া সহজ করতে +[]
মূল্যায়ণ 0
। কেন এটি সত্য তা নিশ্চিত করার জন্য, অ্যানারি + অপারেটরটি পরীক্ষা করে দেখুন এবং সামান্য মারাত্মক ট্রেইলটি অনুসরণ করুন যা টোপ্রিমিটিভ দিয়ে খালি অ্যারেটিকে একটি ফাঁকা স্ট্রিংয়ে রূপান্তরিত করে শেষ পর্যন্ত টনবার0
দ্বারা রূপান্তরিত করে । আমরা এখন প্রতিটি উদাহরণের জন্য বিকল্প করতে পারি :0
+[]
( ++[[]][0] ) + [0]
সহজ ইতিমধ্যে। যেমন ++[[]][0]
, এটি প্রিফিক্স ইনক্রিমেন্ট অপারেটর ( ++
) এর সংমিশ্রণ , একটি অ্যারে আক্ষরিক যা একটি খালি অ্যারে ( [[]]
) এবং অ্যারে আক্ষরিক দ্বারা সংজ্ঞায়িত অ্যারেতে ডাকা একটি সম্পত্তি অ্যাক্সেসর ( [0]
) এর সাথে একটি অ্যারের সংজ্ঞা দেয়।
সুতরাং, আমরা [[]][0]
কেবল সহজ করতে পারি []
এবং আমাদের আছে ++[]
, তাই না? আসলে, এটি কেস নয় কারণ মূল্যায়ন ++[]
একটি ত্রুটি ছুড়ে দেয়, যা প্রাথমিকভাবে বিভ্রান্ত বলে মনে হতে পারে। তবে এর প্রকৃতি সম্পর্কে একটু চিন্তাভাবনা ++
এটিকে পরিষ্কার করে দেয়: এটি একটি পরিবর্তনশীল (উদাঃ ++i
) বা কোনও বস্তুর সম্পত্তি (উদাঃ ++obj.count
) বৃদ্ধি করার জন্য ব্যবহৃত হয় । এটি কেবল কোনও মানকে মূল্যায়ন করে না, এটি সেই মানটি কোথাও সঞ্চয় করে। এর ক্ষেত্রে ++[]
এটির নতুন মানটি (এটি যাই হোক না কেন) রাখার মতো কোথাও নেই কারণ কোনও অবজেক্টের সম্পত্তি বা আপডেটের জন্য ভেরিয়েবলের কোনও উল্লেখ নেই। স্পেসের ভাষায়, এটি অভ্যন্তরীণ পুতভালিউ অপারেশন দ্বারা আচ্ছাদিত , যা প্রিফিক্স ইনক্রিমেন্ট অপারেটর বলে।
তাহলে, কি করে ++[[]][0]
? ভাল, অনুরূপ যুক্তি দ্বারা +[]
, অভ্যন্তরীণ অ্যারে রূপান্তরিত হয় 0
এবং 1
আমাদের মান একটি চূড়ান্ত মান দিতে এই মান বৃদ্ধি করা হয় 1
। 0
বাইরের অ্যারেতে সম্পত্তিটির মান আপডেট করা হয় 1
এবং পুরো এক্সপ্রেশনটি এতে মূল্যায়ন করে 1
।
এটি আমাদের সাথে ছেড়ে যায়
1 + [0]
... যার একটি সহজ ব্যবহার উপরন্তু অপারেটর । উভয় অপারেশন প্রথমে আদিমগুলিতে রূপান্তরিত হয় এবং যদি আদিম মান একটি স্ট্রিং হয় তবে স্ট্রিং কনকেন্টেশন সম্পাদন করা হয়, অন্যথায় সংখ্যাসূচক সংযোজন সঞ্চালিত হয়। [0]
রূপান্তরিত হয় "0"
, সুতরাং স্ট্রিং সংক্ষেপণ ব্যবহৃত হয়, উত্পাদন করা হয় "10"
।
চূড়ান্ত একদিকে যেমন, যা তাত্ক্ষণিকভাবে দৃশ্যমান হয় না তা হ'ল যে কোনও একটি toString()
বা valueOf()
পদ্ধতিতে ওভাররাইড করা Array.prototype
অভিব্যক্তির ফলাফলকে বদলে দেবে, কারণ কোনও বস্তুকে আদিম মান হিসাবে রূপান্তর করার সময় উপস্থিত থাকলে উভয়ই পরীক্ষা করা হয় এবং ব্যবহৃত হয়। উদাহরণস্বরূপ, নিম্নলিখিত
Array.prototype.toString = function() {
return "foo";
};
++[[]][+[]]+[+[]]
... উত্পাদন করে "NaNfoo"
। কেন এটি ঘটে তা পাঠকদের জন্য অনুশীলন হিসাবে রেখে দেওয়া হয়েছে ...
আসুন এটি সহজ করুন:
++[[]][+[]]+[+[]] = "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 সহ একটি অ্যারে।
তারপরে জেএস 1 + [0]
এইভাবে Number + Array
প্রকাশের মূল্যায়ন করে । তারপরে ইসিএমএ স্পেসিফিকেশন কাজ করে: +
অপারেটর 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