javascript - কেন++[[]][+[]]+[+[]] স্ট্রিংটি "10" ফেরত দেয়?




syntax (6)

এটি বৈধ এবং জাভাস্ক্রিপ্টে স্ট্রিংটি "10" করে ( এখানে আরও উদাহরণ ):

console.log(++[[]][+[]]+[+[]])

কেন? এখানে কি হচ্ছে?


  1. ইউনিনারি প্লাস দেওয়া স্ট্রিং সংখ্যা রূপান্তর
  2. বৃদ্ধি অপারেটর স্ট্রিং রূপান্তর এবং 1 দ্বারা বৃদ্ধি
  3. [] == ''। খালি স্ট্রিং
  4. + '' বা + [] মূল্যায়ন 0।

    ++[[]][+[]]+[+[]] = 10 
    ++[''][0] + [0] : First part is gives zeroth element of the array which is empty string 
    1+0 
    10

+ [] মূল্যায়ন 0 [...] তারপর সংক্ষেপে (+ অপারেশন) এটি অ্যারের সামগ্রীটিকে তার স্ট্রিং প্রতিনিধিত্বের সাথে রূপান্তরিত করে যার মধ্যে রয়েছে কমা দিয়ে যোগ করা উপাদানগুলি।

অ্যারে সূচী গ্রহণের মত অন্য কিছু (+ অপারেশন তুলনায় grater অগ্রাধিকার আছে) আদর্শ এবং আকর্ষণীয় কিছু নয়।


এই প্রশ্নটির উত্তর দেওয়ার জন্য একটি ব্লগ পোস্ট থেকে নিম্নলিখিতটি অনুসরণ করা হয়েছে যা আমি এই পোস্টটি বন্ধ করার সময় পোস্ট করেছি। লিংকগুলি (এর একটি HTML অনুলিপি) ECMAScript 3 spec, এখনও আজকের সাধারণভাবে ব্যবহৃত ব্রাউজারগুলিতে জাভাস্ক্রিপ্টের বেসলাইন।

প্রথমত, একটি মন্তব্য: এই ধরনের অভিব্যক্তি কোনও (সনে) উৎপাদন পরিবেশে দেখাতে পারে না এবং শুধুমাত্র পাঠককে জাভাস্ক্রিপ্টের নোংরা প্রান্তগুলি কতটা ভালভাবে জানে তা ব্যায়াম হিসাবে ব্যবহার করা হয়। সাধারণ নীতি যা জাভাস্ক্রিপ্ট অপারেটরগুলি প্রকারের মধ্যে রূপান্তরিতভাবে রূপান্তরিত হয় তা সাধারণ রূপান্তরগুলির মতোই কার্যকর, তবে এই ক্ষেত্রে বিস্তারিত বিশদ নয়।

অভিব্যক্তি ++[[]][+[]]+[+[]] শুরুতে পরিবর্তে বদলে যাওয়া এবং অস্পষ্ট চেহারা হতে পারে, তবে আসলে পৃথক অভিব্যক্তিগুলিতে তুলনামূলকভাবে সহজে ভাঙ্গা যায়। নীচে আমি কেবল স্বচ্ছতার জন্য বন্ধনী যুক্ত করেছি; আমি আপনাকে আশ্বস্ত করতে পারি তারা কিছুই পরিবর্তন করে না, তবে আপনি যদি এটি যাচাই করতে চান তবে গ্রুপিং অপারেটর সম্পর্কে পড়তে বিনা দ্বিধায়। সুতরাং, অভিব্যক্তি আরো পরিষ্কারভাবে হিসাবে লেখা যেতে পারে

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

এই ভেঙে ফেলা, আমরা পর্যবেক্ষণ করে সহজ করতে পারি যে +[] 0 মূল্যায়ন করে। নিজেকে কেন সন্তুষ্ট করার জন্য, unary + অপারেটরটি দেখুন এবং সামান্য ToPrimitive ট্রেল অনুসরণ করুন যা ToPrimitive খালি অ্যারেকে খালি স্ট্রিং রূপে রূপান্তরিত করে, যা অবশেষে ToNumber দ্বারা 0 রূপে রূপান্তরিত হয়। আমরা এখন প্রতিটি ইনস্ট্যান্সের জন্য 0 প্রতিস্থাপন করতে পারি: +[] :

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

ইতিমধ্যে সহজ। ++[[]][0] , এটি bclary.com/2004/11/07/#a-11.4.4 ( ++ ) এর সমন্বয়, একটি অ্যারের আক্ষরিক একটি উপাদান যা একটি খালি অ্যারের ( [[]] ) এবং একটি সম্পত্তি অ্যাক্সেসার ( [0] ) অ্যারে আক্ষরিক দ্বারা সংজ্ঞায়িত অ্যারে বলা।

সুতরাং, আমরা [[]][0] সহজে [[]][0] করতে পারি এবং আমাদের ++[] , ঠিক আছে? আসলে, এই ক্ষেত্রে না কারণ মূল্যায়ন ++[] একটি ত্রুটি ছোঁড়ে, যা প্রাথমিকভাবে বিভ্রান্তিকর মনে হতে পারে। যাইহোক, ++ প্রকৃতির সম্পর্কে একটু চিন্তা এই পরিষ্কার করে তোলে: এটি একটি পরিবর্তনশীল (উদাহরণস্বরূপ ++i ) বা একটি বস্তুর সম্পত্তি বৃদ্ধি করার জন্য ব্যবহৃত হয় (যেমন ++obj.count )। এটি একটি মান মূল্যায়ন করে না, এটি কোথাও যে মান সঞ্চয় করে। ++[] ক্ষেত্রে, এটি নতুন মান (যাই হোক না কেন এটি হতে পারে) রাখতে কোথাও নেই কারণ একটি বস্তুর সম্পত্তি বা পরিবর্তনশীল আপডেট করার কোন রেফারেন্স নেই। স্পিক পদগুলিতে, এটি অভ্যন্তরীণ PutValue অপারেশন দ্বারা আচ্ছাদিত, যা উপসর্গ বৃদ্ধি অপারেটর দ্বারা বলা হয়।

তাহলে, ++[[]][0] কি করে? আচ্ছা, একই যুক্তি অনুসারে +[] , অভ্যন্তরীণ অ্যারে 0 রূপে রূপান্তরিত হয় এবং এই মানটি 1 দ্বারা আমাদেরকে 1 চূড়ান্ত মান দিতে 1 দ্বারা বাড়ানো হয়। বাহ্যিক অ্যারেতে সম্পত্তি 0 এর মানটি 1 টিতে আপডেট করা হয় এবং সমগ্র অভিব্যক্তিটি 1 মূল্যায়ন করে।

এই সঙ্গে আমাদের ছেড়ে

1 + [0]

... যা যোগ অপারেটর একটি সহজ ব্যবহার। উভয় operands প্রথম ToPrimitive হয় এবং যদি আদিম মান একটি স্ট্রিং হয়, স্ট্রিং concatenation সঞ্চালিত হয়, অন্যথায় সাংখ্যিক সংযোজন সঞ্চালিত হয়। [0] "0" তে রূপান্তরিত হয়, তাই স্ট্রিং কনক্যাটেনেশন ব্যবহার করা হয়, "10"

একটি চূড়ান্ত valueOf() হিসাবে, এমন কিছু যা অবিলম্বে স্পষ্ট নাও হতে পারে তা হল valueOf() toString() বা valueOf() পদ্ধতিগুলির Array.prototype উপরে 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"

সংখ্যার ব্যবধানে "10" এ একটি অভিব্যক্তি মূল্যায়ন করার সর্বনিম্ন সম্ভাব্য উপায়গুলি হল:

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

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

// ========== ব্যাখ্যা ========== \\

+!+[] : +[] !0 রূপান্তর !0 রূপান্তর true+true রূপান্তর 1. -~[] = -(-1) যা 1

[+[]] : +[] রূপান্তর 0 [0] একটি একক উপাদান 0 সঙ্গে একটি অ্যারে।

তারপর JS 1 + [0] মূল্যায়ন করে, এভাবে Number + Array এক্সপ্রেশন। তারপর ECMA স্পেসিফিকেশন কাজ করে: + অপারেটর মূল Object প্রোটোটাইপ থেকে toString()/valueOf() ফাংশন কল করে উভয় toString()/valueOf() স্ট্রিংয়ে রূপান্তরিত করে। একটি অভিব্যক্তি উভয় অপারেটিং শুধুমাত্র সংখ্যা যদি এটি একটি additive ফাংশন হিসাবে কাজ করে। কৌতুক সহজেই অ্যারে একটি উপাদান সংযুক্ত স্ট্রিং উপস্থাপনা মধ্যে তাদের উপাদান রূপান্তর।

কিছু উদাহরণ:

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

NaN দুটি Objects সংযোজন ফলাফলের একটি চমৎকার ব্যতিক্রম রয়েছে:

[] + []   //    ""
[1] + [2] //    "12"
{} + {}   //    NaN
{a:1} + {b:2}     //    NaN
[1, {}] + [2, {}] //    "1,[object Object]2,[object Object]"

++[[]][+[]] => 1 // [+[]] = [0], ++0 = 1
[+[]] => [0]

তারপর আমরা একটি স্ট্রিং concatenation আছে

1+[0].toString() = 10




syntax