জাভাস্ক্রিপ্টে ব্যাপ্তি তৈরি হচ্ছে - অদ্ভুত সিনট্যাক্স


129

আমি এসএস-আলোচনা মেলিং তালিকায় নিম্নলিখিত কোডটিতে প্রবেশ করেছি:

Array.apply(null, { length: 5 }).map(Number.call, Number);

এটি উত্পাদন করে

[0, 1, 2, 3, 4]

কেন এই কোডের ফলাফল? এখানে কি হচ্ছে?


2
আইএমও Array.apply(null, Array(30)).map(Number.call, Number)পড়তে সহজ কারণ এটি সরল বস্তুটি একটি অ্যারে বলে ভান করা এড়ায়।
fncomp

10
@fncomp দয়া করে আসলে একটি ব্যাপ্তি তৈরি করতে ব্যবহার করবেন না । কেবল এটি সোজা পদ্ধতির চেয়ে ধীর নয় - এটি বোঝার মতো প্রায় সহজ নয়। এখানে সিনট্যাক্সটি বোঝা শক্ত (ভাল, সত্যই এপিআই এবং সিনট্যাক্স নয়) যা এটি একটি আকর্ষণীয় প্রশ্ন কিন্তু ভয়াবহ উত্পাদন কোড আইএমও করে তোলে।
বেনিয়ামিন গ্রুইনবাউম

হ্যাঁ, কাউকে এটি ব্যবহার করার পরামর্শ দিচ্ছে না তবে মনে হয়েছে এটি পড়ার জন্য এখনও সহজ ছিল, বস্তুর আক্ষরিক সংস্করণের তুলনায়।
fncomp

1
আমি নিশ্চিত না যে কেউ কেন এটি করতে চাইবে। এইভাবে অ্যারে তৈরি করতে যে পরিমাণ সময় লাগে এটি কিছুটা কম সেক্সি তবে আরও দ্রুততর উপায়ে করা যেতে পারে: jsperf.com/basic-vs-extreme
এরিক হোডনস্কি

উত্তর:


263

এই "হ্যাক" বোঝার জন্য কয়েকটি বিষয় বোঝার প্রয়োজন:

  1. কেন আমরা শুধু করি না Array(5).map(...)
  2. কিভাবে Function.prototype.applyআর্গুমেন্ট পরিচালনা করে
  3. কীভাবে Arrayএকাধিক যুক্তি পরিচালনা করে
  4. কীভাবে Numberফাংশন আর্গুমেন্ট পরিচালনা করে
  5. কি Function.prototype.callকরে

এগুলি জাভাস্ক্রিপ্টে বরং উন্নততর বিষয়, তাই এটি বরং-দীর্ঘতর হবে। আমরা উপর থেকে শুরু করব। বকল!

১.কেন না কেন Array(5).map?

আসলে কি অ্যারে? একটি নিয়মিত অবজেক্ট, পূর্ণসংখ্যা কীগুলি ধারণ করে, যা মানকে মানচিত্র করে। lengthএটিতে অন্যান্য বিশেষ বৈশিষ্ট্য রয়েছে, উদাহরণস্বরূপ theন্দ্রজালিক ভেরিয়েবল, তবে এটির মূল বিষয় এটি key => valueঅন্য নিয়মের মতো একটি নিয়মিত মানচিত্র। একটু অ্যারে নিয়ে খেলি, আমরা কি?

var arr = ['a', 'b', 'c'];
arr.hasOwnProperty(0); //true
arr[0]; //'a'
Object.keys(arr); //['0', '1', '2']
arr.length; //3, implies arr[3] === undefined

//we expand the array by 1 item
arr.length = 4;
arr[3]; //undefined
arr.hasOwnProperty(3); //false
Object.keys(arr); //['0', '1', '2']

আমরা অ্যারে আইটেমের সংখ্যা এবং অ্যারেতে arr.lengthথাকা key=>valueম্যাপিংয়ের সংখ্যার মধ্যে অন্তর্নিহিত পার্থক্য পেয়েছি, যা এর চেয়ে আলাদা হতে পারে arr.length

অ্যারের মাধ্যমে প্রসারিত করার ফলে কোনও নতুন ম্যাপিং তৈরি arr.length হয় নাkey=>value , সুতরাং অ্যারের অপরিজ্ঞাত মান রয়েছে না, এটির কীগুলি নেই । এবং যখন আপনি অস্তিত্বহীন সম্পত্তি অ্যাক্সেস করার চেষ্টা করবেন তখন কী ঘটে? আপনি পেতে undefined

এখন আমরা আমাদের মাথা arr.mapকিছুটা উপরে তুলতে পারি , এবং দেখি কেন এই বৈশিষ্ট্যগুলির উপরে চলতে পছন্দ করে না। যদি arr[3]কেবল অপরিবর্তিত থাকে এবং কীটি বিদ্যমান থাকে তবে এই সমস্ত অ্যারে ফাংশনগুলি অন্য মানগুলির মতো এটির উপরে চলে যাবে:

//just to remind you
arr; //['a', 'b', 'c', undefined];
arr.length; //4
arr[4] = 'e';

arr; //['a', 'b', 'c', undefined, 'e'];
arr.length; //5
Object.keys(arr); //['0', '1', '2', '4']

arr.map(function (item) { return item.toUpperCase() });
//["A", "B", "C", undefined, "E"]

আমি ইচ্ছাকৃতভাবে একটি পদ্ধতি কলটি ব্যবহার করে এই পয়েন্টটি আরও প্রমাণ করতে চাইছিলাম যে কীটি নিজেই কখনও ছিল না: কলিংয়ের undefined.toUpperCaseফলে কোনও ত্রুটি বাড়ানো হত, তবে তা হয়নি। এটি প্রমাণ করার জন্য :

arr[5] = undefined;
arr; //["a", "b", "c", undefined, "e", undefined]
arr.hasOwnProperty(5); //true
arr.map(function (item) { return item.toUpperCase() });
//TypeError: Cannot call method 'toUpperCase' of undefined

এবং এখন আমরা আমার বক্তব্য: কীভাবে Array(N)জিনিসগুলি হয়। বিভাগ 15.4.2.2 প্রক্রিয়া বর্ণনা করে। এখানে প্রচুর পরিমাণে জাম্বু রয়েছে যা আমরা যত্ন করি না, তবে আপনি যদি লাইনগুলির মধ্যে পড়তে পরিচালনা করেন (বা আপনি কেবল আমার উপর এটি বিশ্বাস করতে পারেন তবে তা করবেন না), এটি মূলত এটিকে ফুটিয়ে তোলে:

function Array(len) {
    var ret = [];
    ret.length = len;
    return ret;
}

(অনুমানের অধীনে কাজ করে (যা প্রকৃত অনুমানে যাচাই করা হয়) যা lenবৈধ uint32, এবং কেবলমাত্র কোনও সংখ্যার মান নয়)

সুতরাং এখন আপনি দেখতে পাচ্ছেন কেন কেন কাজ করা Array(5).map(...)হবে না - আমরা lenঅ্যারেতে আইটেমগুলি সংজ্ঞায়িত করি না , আমরা key => valueম্যাপিংগুলি তৈরি করি না , আমরা কেবল lengthসম্পত্তি পরিবর্তন করি ।

এখন যে আমাদের বাইরে চলে গেছে, আসুন দ্বিতীয় যাদুবিদ্যার দিকে নজর দিন:

2. কিভাবে Function.prototype.applyকাজ করে

applyমূলত যা হয় তা হল একটি অ্যারে নেওয়া এবং এটি একটি ফাংশন কলের আর্গুমেন্ট হিসাবে আনরোল করুন। এর অর্থ হ'ল নিম্নলিখিতগুলি বেশ কিছুটা একই:

function foo (a, b, c) {
    return a + b + c;
}
foo(0, 1, 2); //3
foo.apply(null, [0, 1, 2]); //3

এখন, আমরা applyকেবল argumentsবিশেষ ভেরিয়েবল লগ করে কীভাবে কাজ করে তা দেখার প্রক্রিয়াটি সহজ করতে পারি :

function log () {
    console.log(arguments);
}

log.apply(null, ['mary', 'had', 'a', 'little', 'lamb']);
 //["mary", "had", "a", "little", "lamb"]

//arguments is a pseudo-array itself, so we can use it as well
(function () {
    log.apply(null, arguments);
})('mary', 'had', 'a', 'little', 'lamb');
 //["mary", "had", "a", "little", "lamb"]

//a NodeList, like the one returned from DOM methods, is also a pseudo-array
log.apply(null, document.getElementsByTagName('script'));
 //[script, script, script, script, script, script, script, script, script, script, script, script, script, script, script, script, script, script, script, script]

//carefully look at the following two
log.apply(null, Array(5));
//[undefined, undefined, undefined, undefined, undefined]
//note that the above are not undefined keys - but the value undefined itself!

log.apply(null, {length : 5});
//[undefined, undefined, undefined, undefined, undefined]

দ্বিতীয় থেকে শেষের উদাহরণে আমার দাবি প্রমাণ করা সহজ:

function ahaExclamationMark () {
    console.log(arguments.length);
    console.log(arguments.hasOwnProperty(0));
}

ahaExclamationMark.apply(null, Array(2)); //2, true

(হ্যাঁ, পাং উদ্দেশ্য) key => valueম্যাপিং অ্যারে আমরা ধরে পাশ অস্তিত্ব পারে নি apply, কিন্তু এটা অবশ্যই বিদ্যমান argumentsপরিবর্তনশীল। শেষ উদাহরণটি একই কারণে এটি কাজ করে: আমরা যে বস্তুটি পাস করি তার মধ্যে কীগুলি বিদ্যমান নেই, তবে সেগুলিতে রয়েছে arguments

কেন এমন? আসুন অনুচ্ছেদ 15.3.4.3 দেখুন , যেখানে Function.prototype.applyসংজ্ঞায়িত করা হয়েছে। বেশিরভাগ জিনিসগুলির জন্য আমরা যত্ন করি না, তবে এখানে আকর্ষণীয় অংশটি রয়েছে:

  1. আর্গুমেন্টের "দৈর্ঘ্য" সহ আर्गারির অভ্যন্তরীণ পদ্ধতিটিকে [[পান]] কল করার ফলাফল হতে দেওয়া যাক।

যা মূলত অর্থ: argArray.length। স্পেকটি আইটেমগুলির forউপর একটি সাধারণ লুপ করতে এগিয়ে চলেছে length, যার listসাথে সম্পর্কিত মানগুলি তৈরি হয় ( listএটি কিছু অভ্যন্তরীণ ভুডু তবে এটি মূলত একটি অ্যারে)। খুব, খুব আলগা কোডের ক্ষেত্রে:

Function.prototype.apply = function (thisArg, argArray) {
    var len = argArray.length,
        argList = [];

    for (var i = 0; i < len; i += 1) {
        argList[i] = argArray[i];
    }

    //yeah...
    superMagicalFunctionInvocation(this, thisArg, argList);
};

সুতরাং argArrayএই ক্ষেত্রে আমাদের যেহেতু নকল করা দরকার তা হ'ল lengthসম্পত্তি সহ একটি বস্তু । এবং এখন আমরা দেখতে পাচ্ছি যে মানগুলি কেন সংজ্ঞায়িত হয় তবে কীগুলি অন হয় না arguments: আমরা key=>valueম্যাপিংগুলি তৈরি করি ।

ভাই, সুতরাং এটি পূর্ববর্তী অংশের চেয়ে কম না হতে পারে। আমরা শেষ করার পরে কেক থাকবে, তাই ধৈর্য ধরুন! তবে, নিম্নলিখিত বিভাগের পরে (যা সংক্ষিপ্ত হবে, আমি প্রতিশ্রুতি দিচ্ছি) আমরা অভিব্যক্তিটি ছিন্ন করতে শুরু করতে পারি। আপনি যদি ভুলে গেছেন তবে প্রশ্নটি ছিল নিম্নলিখিত কাজগুলি কীভাবে করে:

Array.apply(null, { length: 5 }).map(Number.call, Number);

3. কীভাবে Arrayএকাধিক যুক্তি পরিচালনা করে

তাই! আপনি যখন কোনও lengthযুক্তিটি পাস করেন তখন কী ঘটেছিল আমরা তা দেখেছি Array, তবে অভিব্যক্তিতে আমরা বেশ কিছু জিনিসকে আর্গুমেন্ট হিসাবে (পাসওয়ার্ডের 5 টি অ্যারে, undefinedসঠিক হিসাবে) পাস করি । বিভাগ 15.4.2.1 আমাদের কী করতে হবে তা বলে। শেষ অনুচ্ছেদটি আমাদের কাছে গুরুত্বপূর্ণ, এবং এটি সত্যই অদ্ভুতভাবে শব্দযুক্ত, তবে এটি এক প্রকারে ফোটে:

function Array () {
    var ret = [];
    ret.length = arguments.length;

    for (var i = 0; i < arguments.length; i += 1) {
        ret[i] = arguments[i];
    }

    return ret;
}

Array(0, 1, 2); //[0, 1, 2]
Array.apply(null, [0, 1, 2]); //[0, 1, 2]
Array.apply(null, Array(2)); //[undefined, undefined]
Array.apply(null, {length:2}); //[undefined, undefined]

Tada! আমরা বেশ কয়েকটি অপরিবর্তিত মানগুলির একটি অ্যারে পাই এবং আমরা এই অপরিজ্ঞাত মানগুলির একটি অ্যারে ফিরিয়ে আনি।

ভাবের প্রথম অংশ

পরিশেষে, আমরা নিম্নলিখিতটি বোঝাতে পারি:

Array.apply(null, { length: 5 })

আমরা দেখেছি যে এটি 5 টি অপরিজ্ঞাত মান সমেত একটি অ্যারে প্রদান করে, যা সমস্ত অস্তিত্বে রয়েছে keys

এখন, প্রকাশের দ্বিতীয় অংশে:

[undefined, undefined, undefined, undefined, undefined].map(Number.call, Number)

এটি এত সহজ, অ-সংশ্লেষিত অংশ হবে, কারণ এটি এতটা অস্পষ্ট হ্যাকগুলির উপর নির্ভর করে না।

4. কীভাবে Numberইনপুট আচরণ করে

এরকম Number(something)( অধ্যায় 15.7.1 ) ধর্মান্তরিত somethingএকটি সংখ্যা, এবং যে সব হয়। এটি কীভাবে কিছুটা দোষযুক্ত হয়, বিশেষত স্ট্রিংগুলির ক্ষেত্রে, তবে আপনার আগ্রহের ক্ষেত্রে অপারেশনটি 9.3 বিভাগে সংজ্ঞায়িত করা হয়েছে ।

5. গেমস Function.prototype.call

callহয় applyএর ভাই সংজ্ঞায়িত অধ্যায় 15.3.4.4 । আর্গুমেন্টগুলির অ্যারে নেওয়ার পরিবর্তে, এটি প্রাপ্ত হওয়া আর্গুমেন্টগুলি কেবল নেয় এবং তাদের এগিয়ে যায়।

আপনি যখন একের বেশি callএকসাথে শৃঙ্খলাবদ্ধ হন তখন বিষয়গুলি আকর্ষণীয় হয়ে ওঠে, 11 অবধি অদ্ভুতভাবে ক্র্যাঙ্ক করুন:

function log () {
    console.log(this, arguments);
}
log.call.call(log, {a:4}, {a:5});
//{a:4}, [{a:5}]
//^---^  ^-----^
// this   arguments

যা চলছে তা আপনি উপলব্ধি না করা পর্যন্ত এটি বেশ ডাব্লুএইচএফ যোগ্য worthy log.callকেবল একটি ফাংশন, অন্য কোনও ফাংশনের callপদ্ধতির সমতুল্য এবং এর মতো callনিজেই একটি পদ্ধতিও রয়েছে :

log.call === log.call.call; //true
log.call === Function.call; //true

এবং কি করে call? এটি একটি thisArgএবং একগুচ্ছ আর্গুমেন্ট গ্রহণ করে এবং এর প্যারেন্ট ফাংশনটিকে কল করে। আমরা এর মাধ্যমে এটি সংজ্ঞায়িত করতে পারি apply (আবার, খুব আলগা কোড, কাজ করবে না):

Function.prototype.call = function (thisArg) {
    var args = arguments.slice(1); //I wish that'd work
    return this.apply(thisArg, args);
};

কীভাবে এটি নিচে যায় তা ট্র্যাক করা যাক:

log.call.call(log, {a:4}, {a:5});
  this = log.call
  thisArg = log
  args = [{a:4}, {a:5}]

  log.call.apply(log, [{a:4}, {a:5}])

    log.call({a:4}, {a:5})
      this = log
      thisArg = {a:4}
      args = [{a:5}]

      log.apply({a:4}, [{a:5}])

পরবর্তী অংশ, বা .mapএটি সমস্ত

এখনও শেষ হয়নি। আসুন দেখা যাক আপনি যখন বেশিরভাগ অ্যারে পদ্ধতিতে কোনও ফাংশন সরবরাহ করেন তখন কী হয়:

function log () {
    console.log(this, arguments);
}

var arr = ['a', 'b', 'c'];
arr.forEach(log);
//window, ['a', 0, ['a', 'b', 'c']]
//window, ['b', 1, ['a', 'b', 'c']]
//window, ['c', 2, ['a', 'b', 'c']]
//^----^  ^-----------------------^
// this         arguments

যদি আমরা thisনিজেরাই যুক্তি সরবরাহ না করি তবে এটি ডিফল্ট হয় window। আমাদের কলব্যাকটিতে তর্কগুলি যে অর্ডারে সরবরাহ করা হয়েছে সেটির জন্য নোট করুন, এবং আসুন এটি আবার 11 টি করে অদ্ভুত করুন:

arr.forEach(log.call, log);
//'a', [0, ['a', 'b', 'c']]
//'b', [1, ['a', 'b', 'c']]
//'b', [2, ['a', 'b', 'c']]
// ^    ^

হু হু হুয়া ... আসুন কিছুটা ব্যাকআপ দিন। এখানে কি হচ্ছে? আমরা বিভাগ 15.4.4.18 এ দেখতে পাচ্ছি , যেখানে forEachসংজ্ঞায়িত করা হয়েছে, নিম্নলিখিতটি অনেক কিছু ঘটে:

var callback = log.call,
    thisArg = log;

for (var i = 0; i < arr.length; i += 1) {
    callback.call(thisArg, arr[i], i, arr);
}

সুতরাং, আমরা এটি পেয়েছি:

log.call.call(log, arr[i], i, arr);
//After one `.call`, it cascades to:
log.call(arr[i], i, arr);
//Further cascading to:
log(i, arr);

এখন আমরা দেখতে পারি কীভাবে .map(Number.call, Number)কাজ করে:

Number.call.call(Number, arr[i], i, arr);
Number.call(arr[i], i, arr);
Number(i, arr);

যা iবর্তমান সূচকে একটি সংখ্যায় রূপান্তর করে ।

উপসংহারে,

অভিব্যক্তি

Array.apply(null, { length: 5 }).map(Number.call, Number);

দুটি অংশে কাজ করে:

var arr = Array.apply(null, { length: 5 }); //1
arr.map(Number.call, Number); //2

প্রথম অংশে 5 টি অপরিবর্তিত আইটেমের অ্যারে তৈরি করা হয়। দ্বিতীয়টি অ্যারের উপরে চলে যায় এবং সূচকগুলি গ্রহণ করে, ফলস্বরূপ উপাদান সূচকগুলির একটি অ্যারে:

[0, 1, 2, 3, 4]

@ জিরাক দয়া করে নিম্নলিখিতগুলি বুঝতে সাহায্য করুন ahaExclamationMark.apply(null, Array(2)); //2, true। কেন এটা শূণ্য দেখায় 2এবং trueযথাক্রমে? আপনি কি Array(2)এখানে একটি যুক্তি দিয়ে যাচ্ছেন না?
গীক

4
@ গীক আমরা কেবল একটি যুক্তিই পাস করি applyতবে সেই যুক্তিটি "স্প্ল্যাটেড" ফাংশনে দুটি আর্গুমেন্টে পরিণত হয়। প্রথম applyউদাহরণগুলিতে আপনি এটি আরও সহজে দেখতে পাচ্ছেন । প্রথমটি console.logদেখায় যে প্রকৃতপক্ষে আমরা দুটি আর্গুমেন্ট (দুটি অ্যারে আইটেম) পেয়েছি এবং দ্বিতীয়টি console.logদেখায় যে অ্যারেটির key=>value1 ম স্লটে ম্যাপিং রয়েছে (উত্তরের প্রথম অংশে বর্ণিত)।
জিরাক

4
(কিছু) অনুরোধের কারণে আপনি এখন অডিও সংস্করণটি উপভোগ করতে পারবেন: dl.rodboxusercontent.com/u/24522528/SO-answer.mp3
Zirak

1
মনে রাখবেন যে কোনও নোডলিস্টকে একটি হোস্ট অবজেক্ট হিসাবে কোনও স্থানীয় পদ্ধতিতে পাস log.apply(null, document.getElementsByTagName('script'));করার জন্য কাজ করার প্রয়োজন হয় না এবং কিছু ব্রাউজারে কাজ করে না এবং কোনও [].slice.call(NodeList)নোডলিস্টকে অ্যারেতে রূপান্তর করা তাদের মধ্যেও কাজ করবে না।
রবজি

2
একটি সংশোধন: thisকেবল Windowঅ-কঠোর মোডে ডিফল্ট ।
কমফ্রিচ

21

দাবি অস্বীকার : এটি উপরের কোডটির একটি খুব আনুষ্ঠানিক বর্ণনা - এটি কীভাবে এটি ব্যাখ্যা করতে হয় তা আমি জানি know একটি সহজ উত্তরের জন্য - উপরে জিরাকের দুর্দান্ত উত্তরটি দেখুন। এটি আপনার চেহারায় গভীরতার স্পেসিফিকেশন এবং কম "আহা"।


বেশ কয়েকটি জিনিস এখানে ঘটছে। আসুন এটি কিছুটা ভেঙে দিন।

var arr = Array.apply(null, { length: 5 }); // Create an array of 5 `undefined` values

arr.map(Number.call, Number); // Calculate and return a number based on the index passed

প্রথম লাইন ইন, অ্যারে কন্সট্রাকটর একটি ফাংশন হিসাবে বলা হয় সঙ্গে Function.prototype.apply

  • thisমান nullযা এরে কন্সট্রাকটর (জন্য কোন ব্যাপার না thisএকই this15.3.4.3.2.a. অনুযায়ী প্রেক্ষাপটে যেমন
  • তারপরে new Arrayতাকে lengthসম্পত্তি সহ একটি বস্তু পাস করা বলা হয়ে থাকে - যার ফলে .applyনিম্নলিখিত বিষয়টিতে কারণ হিসাবে সেই বিষয়টিকে তার পক্ষে গুরুত্বপূর্ণ সমস্ত কিছু মনে হয় .apply:
    • আর্গুমেন্টের "দৈর্ঘ্য" সহ আर्गারির অভ্যন্তরীণ পদ্ধতিটিকে [[পান]] কল করার ফলাফল হতে দেওয়া যাক।
  • যেমন, .apply0 থেকে 4 টি আর্গুমেন্টগুলি পাশ করা হয় .length, যেহেতু 0 থেকে 4 ফলনের মানগুলি দিয়ে কল [[Get]]করা অ্যারে { length: 5 }নির্মাতাকে undefinedপাঁচটি আর্গুমেন্টের সাথে ডাকা হয় যার মান undefined(কোনও অবজেক্টের অঘোষিত সম্পত্তি পাওয়া)।
  • অ্যারে কনস্ট্রাক্টরকে 0, 2 বা আরও বেশি যুক্তি দিয়ে ডাকা হয় । নবনির্মিত অ্যারের দৈর্ঘ্যের বৈশিষ্ট্য নির্দিষ্টকরণ অনুসারে আর্গুমেন্টের সংখ্যা এবং একই মানগুলিতে মান সেট করা হয়।
  • এইভাবে var arr = Array.apply(null, { length: 5 });পাঁচটি অপরিশোধিত মানের একটি তালিকা তৈরি করে।

নোট : নোটিশ মধ্যে পার্থক্য এখানে Array.apply(0,{length: 5})এবং Array(5), প্রথম তৈরি পাঁচবার আদিম মান টাইপ undefinedএবং পরেরটির, দৈর্ঘ্য 5. বিশেষভাবে এর একটি খালি অ্যারে তৈরি কারণ .mapএর আচরণ (8.b) এবং বিশেষভাবে [[HasProperty]

সুতরাং একটি কমপ্লায়েন্ট স্পেসিফিকেশনে উপরের কোডটি একই:

var arr = [undefined, undefined, undefined, undefined, undefined];
arr.map(Number.call, Number); // Calculate and return a number based on the index passed

এখন দ্বিতীয় অংশ বন্ধ।

  • Array.prototype.mapNumber.callঅ্যারের প্রতিটি উপাদানকে কলব্যাক ফাংশন (এই ক্ষেত্রে ) কল করে এবং নির্দিষ্ট thisমান ব্যবহার করে (এই ক্ষেত্রে thisমানটিকে `সংখ্যাতে সেট করে )।
  • মানচিত্রে কলব্যাকের দ্বিতীয় পরামিতি (এই ক্ষেত্রে Number.call) সূচক এবং প্রথমটি হ'ল এটির মান।
  • এর অর্থ এই যে Numberসঙ্গে বলা হয় thisযেমন undefined(অ্যারে মান) এবং প্যারামিটার হিসাবে সূচি। সুতরাং এটি মূলত undefinedতার অ্যারে সূচকে প্রতিটি ম্যাপিংয়ের মতো (কল করার পরে থেকে)Number কলিংটি ধরণের রূপান্তর সম্পাদন করে, এক্ষেত্রে সংখ্যা থেকে সংখ্যায় সূচক পরিবর্তন না করে)।

সুতরাং উপরের কোডটি পাঁচটি অপরিজ্ঞাত মান নিয়ে যায় এবং অ্যারেতে প্রতিটি সূচকে মানচিত্র করে।

যে কারণে আমরা আমাদের কোডে ফলাফল পাই।


1
দস্তাবেজের জন্য: মানচিত্র কীভাবে কাজ করে তার জন্য নির্দিষ্টকরণ: es5.github.io/#x15.4.4.19 , মজিলার একটি নমুনা স্ক্রিপ্ট রয়েছে যা বিকাশকারী.মোজিলা.আর.ইন.ইউ /
প্যাট্রিক ইভান্স

1
তবে কেন এটি কেবল সাথে কাজ করে Array.apply(null, { length: 2 })এবং না Array.apply(null, [2])যা Arrayকনস্ট্রাক্টরকে 2দৈর্ঘ্যের মান হিসাবে পাস করে? ফ্রিডল
আন্দ্রেয়াস

@Andreas Array.apply(null,[2])মত হল Array(2)একটি সৃষ্টি যা খালি দৈর্ঘ্য 2 অ্যারে এবং না একটি অ্যারের আদিম মান ধারণকারী undefinedদুই বার। প্রথম অংশের পরে নোটটিতে আমার সাম্প্রতিক সম্পাদনাটি দেখুন, এটি যথেষ্ট পরিষ্কার কিনা এবং যদি না হয় তবে আমি সে সম্পর্কে স্পষ্ট করে বলব।
বেঞ্জামিন গ্রুইনবাউম

আমি প্রথম রানে যেভাবে কাজ করে তা বুঝতে পারি নি ... দ্বিতীয় পাঠের পরে এটি বোঝা যায়। {length: 2}দুটি উপাদান সহ একটি অ্যারের জাল দেয় যা Arrayনির্মাণকারী নতুন তৈরি অ্যারেতে প্রবেশ করান। যেহেতু সত্যিকারের অ্যারে অ্যাক্সেস নেই সেখানে উপস্থিত উপাদানগুলির ফলন undefinedযা পরে inোকানো হয়। দুর্দান্ত কৌশল :)
আন্দ্রে

5

যেমনটি আপনি বলেছেন, প্রথম অংশ:

var arr = Array.apply(null, { length: 5 }); 

5 টি undefinedমানের একটি অ্যারে তৈরি করে ।

দ্বিতীয় অংশটি mapঅ্যারের ফাংশনটিকে কল করছে যা 2 টি আর্গুমেন্ট নেয় এবং একই আকারের একটি নতুন অ্যারে প্রদান করে।

প্রথম যুক্তি যা mapগ্রহণ করে তা আসলে অ্যারের প্রতিটি উপাদানগুলিতে প্রয়োগ করার জন্য একটি ফাংশন, এটি এমন ফাংশন বলে প্রত্যাশিত যা 3 টি আর্গুমেন্ট নেয় এবং একটি মান দেয়। উদাহরণ স্বরূপ:

function foo(a,b,c){
    ...
    return ...
}

যদি আমরা প্রথম তর্ক হিসাবে ফাংশন ফুটি পাস করি তবে এটি প্রতিটি উপাদানের সাথে ডাকা হবে

  • একটি বর্তমান পুনরাবৃত্ত উপাদানটির মান হিসাবে
  • খ বর্তমানের পুনরাবৃত্ত উপাদানগুলির সূচক হিসাবে
  • পুরো মূল অ্যারে হিসাবে সি

দ্বিতীয় আর্গুমেন্টটি যে mapফাংশনটি আপনি প্রথম আর্গুমেন্ট হিসাবে পাস করেন তা হ'ল। তবে এটি ক, খ, বা সি এর ক্ষেত্রে fooহবে না, এটি হবে this

দুটি উদাহরণ:

function bar(a,b,c){
    return this
}
var arr2 = [3,4,5]
var newArr2 = arr2.map(bar, 9);
//newArr2 is equal to [9,9,9]

function baz(a,b,c){
    return b
}
var newArr3 = arr2.map(baz,9);
//newArr3 is equal to [0,1,2]

এবং আরও একটি মাত্র এটি পরিষ্কার করার জন্য:

function qux(a,b,c){
    return a
}
var newArr4 = arr2.map(qux,9);
//newArr4 is equal to [3,4,5]

সুতরাং সংখ্যা.call সম্পর্কে কি?

Number.call এটি একটি ফাংশন যা 2 টি আর্গুমেন্ট গ্রহণ করে এবং একটি সংখ্যার সাথে দ্বিতীয় যুক্তিটি পার্স করার চেষ্টা করে (আমি নিশ্চিত না যে এটি প্রথম যুক্তি দিয়ে কী করে)।

যেহেতু দ্বিতীয় আর্গুমেন্টটি mapপাস করছে তা হ'ল সূচক, সেই মানটি যে সূচকে নতুন অ্যারেতে স্থাপন করা হবে তা সূচকের সমান। ঠিক bazউপরের উদাহরণে ফাংশনটির মতো । Number.callসূচককে বিশ্লেষণ করার চেষ্টা করবে - এটি স্বাভাবিকভাবে একই মানটি ফিরিয়ে দেবে।

mapআপনার কোডে ফাংশনটিতে আপনি যে দ্বিতীয় তর্কটি পাস করেছেন তা আসলে ফলাফলের উপর প্রভাব ফেলবে না। আমি ভুল হলে আমাকে সংশোধন করুন, দয়া করে।


1
Number.callসংখ্যায় যুক্তিগুলি পার্স করে এমন কোনও বিশেষ কার্য নয়। এটা ঠিক === Function.prototype.call। শুধুমাত্র দ্বিতীয় যুক্তি, যে ফাংশনটি পাস হয়ে যায়this করতে -value call, প্রাসঙ্গিক হয় - .map(eval.call, Number), .map(String.call, Number)এবং .map(Function.prototype.call, Number)সব সমতুল্য।
বার্গি

0

একটি অ্যারে কেবল 'দৈর্ঘ্য' ক্ষেত্র এবং কিছু পদ্ধতি (যেমন পুশ) সমন্বিত একটি অবজেক্ট। সুতরাং var arr = { length: 5}আরআর মূলত একটি অ্যারের মতোই যেখানে ক্ষেত্রগুলি 0..4 এর পূর্বনির্ধারিত মান রয়েছে যা অপরিজ্ঞাত (অর্থাত arr[0] === undefinedসত্য)।
দ্বিতীয় অংশ হিসাবে, মানচিত্র, নামটি বোঝা যায়, একটি অ্যারে থেকে নতুন অংশে মানচিত্র। এটি মূল অ্যারেটি অনুসরণ করে এবং প্রতিটি আইটেমের ম্যাপিং-ফাংশনটি আহ্বান করে তা করে।

যা বাকি আছে তা আপনাকে বোঝানোর জন্য যে ম্যাপিং-ফাংশনের ফলাফলটি সূচক। কৌশলটি 'কল' (*) নামক পদ্ধতিটি ব্যবহার করা হয় যা প্রথম প্যারামটিকে 'এই' প্রসঙ্গ হিসাবে সেট করা হয় এবং দ্বিতীয়টি প্রথম পরম (এবং এই জাতীয়) হয়ে যায় সেই ছোট ব্যতিক্রম সহ একটি ফাংশনকে আহ্বান করে। কাকতালীয়ভাবে, যখন ম্যাপিং-ফাংশনটি শুরু করা হয়, তখন দ্বিতীয় পরম সূচক হয়।

সর্বশেষে তবে সর্বনিম্ন নয়, যে পদ্ধতিটি আহ্বান করা হয়েছে তা হ'ল নাম্বার "শ্রেণি", এবং আমরা জেএসে জানি, একটি "ক্লাস" কেবল একটি ফাংশন এবং এটির (সংখ্যা) প্রথম পরমটির মান হওয়ার প্রত্যাশা করে।

(*) ফাংশনের প্রোটোটাইপে পাওয়া যায় (এবং সংখ্যাটি একটি ফাংশন)।

মশাল


1
[undefined, undefined, undefined, …]এবং new Array(n)বা {length: n}- এর মধ্যে একটি বিরাট পার্থক্য রয়েছে - পরবর্তীগুলি বিচ্ছিন্ন , অর্থাত্ তাদের কোনও উপাদান নেই। এটি এর জন্য খুব প্রাসঙ্গিক mapএবং এজন্যই বিজোড় Array.applyব্যবহার করা হয়েছিল।
বার্গি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.