[] .ForEach.call () জাভাস্ক্রিপ্টে কি করে?


134

আমি কোডের কয়েকটি স্নিপেটগুলি দেখছিলাম এবং আমি নোড তালিকার উপরে একটি ফাংশন কল করার জন্য একাধিক উপাদানকে দেখতে পেয়েছি যার জন্য একটি ফর অ্যারে প্রয়োগ করা হয়েছে ach

উদাহরণস্বরূপ আমার কাছে এমন কিছু রয়েছে:

[].forEach.call( document.querySelectorAll('a'), function(el) {
   // whatever with the current node
});

তবে আমি বুঝতে পারি না এটি কীভাবে কাজ করে। কেউ আমাকে forEach এর সামনে ফাঁকা অ্যারের আচরণ এবং কীভাবে callকাজ করে তা ব্যাখ্যা করতে পারে ?

উত্তর:


202

[]একটি অ্যারে হয়।
এই অ্যারেটি মোটেই ব্যবহৃত হয় না।

এটি পৃষ্ঠাতে রাখা হচ্ছে, কারণ অ্যারে ব্যবহার করা আপনাকে অ্যারে প্রোটোটাইপগুলিতে অ্যাক্সেস দেয় .forEach

এটি টাইপিংয়ের চেয়ে খুব দ্রুত Array.prototype.forEach.call(...);

এর পরে, forEachএকটি ফাংশন যা ইনপুট হিসাবে একটি ফাংশন নেয় ...

[1,2,3].forEach(function (num) { console.log(num); });

... এবং প্রতিটি উপাদানের জন্য this(যেখানে thisঅ্যারে-এর মতো রয়েছে, এতে এটি রয়েছে lengthএবং আপনি এর অংশগুলি যেমন অ্যাক্সেস করতে পারেন this[1]) এটি তিনটি জিনিস পাস করবে:

  1. অ্যারের মধ্যে উপাদান
  2. উপাদানটির সূচক (তৃতীয় উপাদানটি পাস হবে 2)
  3. অ্যারের একটি রেফারেন্স

শেষ পর্যন্ত, .callএটি একটি প্রোটোটাইপ যা ফাংশনগুলি থাকে (এটি একটি ফাংশন যা অন্য ফাংশনগুলির জন্য ডাকে)। এটি প্রথম যুক্তি হিসাবে গ্রহণ করবে এবং প্রথম তর্ক হিসাবে আপনি যা যা করেছেন তার সাথে নিয়মিত ফাংশনটির অভ্যন্তর
.callপ্রতিস্থাপন করবে ( বা " প্রতিদিনের জেএসে ব্যবহার করবে , বা আপনি যা যা করেছেন তা হবে" কঠোর মোডে "থাকলে)। বাকি আর্গুমেন্টগুলি মূল ফাংশনে পাস করা হবে। thiscallundefinednullwindow

[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
    console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"

অতএব, আপনি forEachফাংশনটি কল করার জন্য একটি দ্রুত উপায় তৈরি করছেন , এবং আপনি thisখালি অ্যারে থেকে সমস্ত <a>ট্যাগের একটি তালিকাতে পরিবর্তন করছেন এবং প্রতিটি <a>ক্রম অনুসারে আপনি প্রদত্ত ফাংশনটি কল করছেন।

সম্পাদনা

লজিকাল উপসংহার / পরিষ্কার

নীচে, একটি নিবন্ধের লিঙ্কটি রয়েছে যাতে বোঝা যায় যে আমরা কার্যকরী প্রোগ্রামিংয়ের চেষ্টাগুলি স্ক্র্যাপ করি এবং প্রতিবার ম্যানুয়াল, ইনলাইন লুপিংয়ের সাথে লেগে থাকি কারণ এই সমাধানটি হ্যাক-ইশ এবং কদর্য।

আমি বলতে চাই যে .forEachতার চেহারা থেকে কম সহায়ক, .map(transformer), .filter(predicate), .reduce(combiner, initialValue), এটা এখনও কাজগুলি করে যখন সমস্ত আপনি কি সত্যিই কাজ করতে চান বহির্বিশ্বের (না অ্যারে), এন-বার সংশোধন, যখন উভয় ব্যবহার করতে পারছে arr[i]বা i

সুতরাং আমরা কীভাবে এই বৈষম্যকে মোকাবিলা করব, যেহেতু মোটো স্পষ্টভাবে একজন প্রতিভাবান এবং জ্ঞানবান লোক, এবং আমি কল্পনা করতে চাই যে আমি জানি আমি কী করছি / কোথায় যাচ্ছি (এখন এবং তার পরে ... ... অন্যান্য এটি প্রথম বারের প্রথম শেখা)?

উত্তরটি আসলে বেশ সহজ, এবং আঙ্কেল বব এবং স্যার ক্রকফোর্ড উভয়ের মুখোমুখি হবে, তদারকির কারণে:

এটা পরিষ্কার

function toArray (arrLike) { // or asArray(), or array(), or *whatever*
  return [].slice.call(arrLike);
}

var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);

এখন আপনি যদি এটি জিজ্ঞাসা করছেন যে আপনার এটি করা দরকার কিনা, আপনি নিজেই উত্তরটি উত্তম হতে পারে না ...
এই সঠিক জিনিসটি আজকাল উচ্চতর অর্ডার বৈশিষ্ট্যযুক্ত প্রতিটি ...?
আপনি যদি লোড্যাশ বা আন্ডারস্কোর বা এমনকি jQuery ব্যবহার করেন তবে সেগুলি সমস্ত উপাদানগুলির একটি সেট নেওয়ার এবং এন-বার একটি ক্রিয়া সম্পাদন করার উপায় রয়েছে।
আপনি যদি এই জাতীয় জিনিস ব্যবহার না করে থাকেন তবে সর্বকথায় নিজের লেখা write

lib.array = (arrLike, start, end) => [].slice.call(arrLike, start, end);
lib.extend = function (subject) {
  var others = lib.array(arguments, 1);
  return others.reduce(appendKeys, subject);
};

ES6 (ES2015) এবং এর বাইরেও আপডেট

কেবলমাত্র একটি slice( )/ array( )/ ইত্যাদি সহায়ক পদ্ধতি যাঁরা অ্যারে ব্যবহার করে (যেমনটি করা উচিত) যেমন তালিকা ব্যবহার করতে চান তাদের জীবনকে সহজতর করে তুলছেন না, তবে তুলনামূলকভাবে নিকটবর্তী ES6 + ব্রাউজারগুলিতে অপারেশন করার বিলাসিতা রয়েছে এমন লোকদের জন্য ভবিষ্যতে বা বাবেলে "ট্রান্সপ্লাইং" এর আজ আপনার ভাষা অন্তর্নির্মিত রয়েছে যা এই ধরণের জিনিসটিকে অপ্রয়োজনীয় করে তোলে।

function countArgs (...allArgs) {
  return allArgs.length;
}

function logArgs (...allArgs) {
  return allArgs.forEach(arg => console.log(arg));
}

function extend (subject, ...others) { /* return ... */ }


var nodeArray = [ ...nodeList1, ...nodeList2 ];

সুপার-ক্লিন এবং খুব দরকারী।
দেখুন বিশ্রাম এবং ছড়িয়ে অপারেটার; বাবেলজেএস সাইটে এগুলি ব্যবহার করে দেখুন; যদি আপনার টেক স্ট্যাকটি যথাযথ হয় তবে এগুলিকে বাবেল এবং একটি বিল্ড স্টেপ সহ উত্পাদনে ব্যবহার করুন।


অ-অ্যারে থেকে আরেতে রূপান্তরটি ব্যবহার না করতে পারা করার কোনও উপযুক্ত কারণ নেই ... ... আপনার কোডটি এমন কোনও কুৎসিত লাইনটি পাস্টিং ব্যতীত আর কিছুই না করে গোলমাল করবেন না , সর্বত্র।


আমি যদি কিছু করি তবে আমি কিছুটা বিভ্রান্ত কারণ: কনসোল.লগ (এটি); আমি সর্বদা উইন্ডো অবজেক্টটি পেয়ে যাব এবং আমি ভেবেছিলাম যে। কলটি এর মান পরিবর্তন করে
মুহাম্মদ সালেহ

.call নেই এর মান পরিবর্তন this, যার কারণে আপনি ব্যবহার করছেন callforeach সঙ্গে। যদি forEach এর মতো দেখতে লাগে forEach (fn) { var i = 0; var len = this.length; for (; i < length; i += 1) { fn( this[i], i, this ); }তবে thisবলার পরিবর্তে এর forEach.call( newArrLike )অর্থ এটি সেই নতুন অবজেক্টটিকে ব্যবহার করবে this
নর্গার্ড

2
@MuhammadSaleh .callমান পরিবর্তন করে না thisতোমার কি পাস ভেতরে forEach, .callমান পরিবর্তন this foreach ভেতরে । আপনি যে ফাংশনটি চেয়েছিলেন thisসেখান থেকে কেন পাস না হওয়ার বিষয়ে যদি আপনি বিভ্রান্ত হন তবে আপনার জাভাস্ক্রিপ্টের forEachআচরণটি সন্ধান করা উচিত this। একটি সংযোজন, প্রযোজ্য শুধুমাত্র এখানে (এবং মানচিত্র / ফিল্টার / কমাতে) হিসাবে, সেখানে একটি দ্বিতীয় যুক্তি forEach, যা সেট thisফাংশন ভিতরে arr.forEach(fn, thisInFn)বা [].forEach.call(arrLike, fn, thisInFn);বা শুধু ব্যবহার .bind; arr.forEach(fn.bind(thisInFn));
নরগার্ড

1
পছন্দ করুন []শুধু তাই আপনি যা করতে পারেন যে একটি অ্যারের হিসাবে, পদ্ধতি, এবং পরিবর্তন সেট আপনার উপর কাজ করতে চান। ভালো দেখায়: আছে ছাড়া সেটে অভ্যন্তরীণ কালো জাদু ভেতরে সমান কি আপনি হিসাবে পাস । .call.forEachthis.callfunction (thisArg, a, b, c) { var method = this; method(a, b, c); }thismethodthisArg
নর্গার্ড

1
এত সংক্ষেপে ... অ্যারে.ফ্রোম ()?
জাকিয়াস

53

querySelectorAllপদ্ধতি একটি ফেরৎ NodeListযা একটি অ্যারের অনুরূপ, কিন্তু এটা বেশ একটি অ্যারের না। অতএব, এটির কোনও forEachপদ্ধতি নেই (যা অ্যারে অবজেক্টগুলির মাধ্যমে উত্তরাধিকারী হয় Array.prototype)।

যেহেতু একটি NodeListএকটি অ্যারের অনুরূপ, অ্যারে পদ্ধতিগুলি আসলে এটিতে কাজ করবে, সুতরাং [].forEach.callআপনি ব্যবহারের মাধ্যমে Array.prototype.forEachপদ্ধতিটির প্রেক্ষাপটে অনুরোধ করছেন NodeList, যেন আপনি সহজভাবে করতে সক্ষম হয়েছিলেন yourNodeList.forEach(/*...*/)

মনে রাখবেন যে খালি অ্যারে আক্ষরিক প্রসারিত সংস্করণটির শর্টকাট, যা আপনি সম্ভবত প্রায়শই দেখতে পাবেন:

Array.prototype.forEach.call(/*...*/);

7
সুতরাং, স্পষ্ট করে বলার জন্য, স্ট্যান্ডার্ড অ্যারেগুলির সাথে প্রতিদিনের অ্যাপ্লিকেশনগুলিতে [].forEach.call(['a','b'], cb)ওভার ব্যবহারের কোনও সুবিধা নেই ['a','b'].forEach(cb), যখন কেবল অ্যারের মতো কাঠামোগুলিগুলির forEachনিজস্ব প্রোটোটাইপ না থাকা নিয়ে পুনরাবৃত্তি করার চেষ্টা করছেন ? এটা কি ঠিক?
ম্যাট ফ্লেচার

2
@ ম্যাটফ্লেচার: হ্যাঁ এটি সঠিক। দু'জনেই কাজ করবে তবে কেন জিনিসগুলিকে জটিল করে তুলবে? কেবল অ্যারেতে সরাসরি পদ্ধতিটি কল করুন।
জেমস আলার্ডার্ডিস

শীতল ধন্যবাদ. এবং কেন জানি না, সম্ভবত কেবল স্ট্রিট ক্রেডিটের জন্যই, ALDI এবং এই জাতীয় প্রবীণ মহিলাকে মুগ্ধ করে। আমি আটকে থাকব [].forEach():)
ম্যাট ফ্লেচার

var section = document.querySelectorAll(".section"); section.forEach((item)=>{ console.log(item.offsetTop) }) ভাল কাজ করে
ডাসলিচ্ট

আইডির পুরানো সংস্করণগুলিতে @ ডাসলিচ নয়! (যে কি করতে , কিন্তু, সমর্থন forEachঅ্যারে উপর NodeList বস্তু, কিন্তু না)
Djave

21

অন্যান্য উত্তরগুলি এই কোডটি খুব ভালভাবে ব্যাখ্যা করেছে, সুতরাং আমি কেবল একটি পরামর্শ যুক্ত করব।

এটি কোডের একটি ভাল উদাহরণ যা সরলতা এবং স্বচ্ছতার জন্য পুনঃসংশ্লিষ্ট হওয়া উচিত। আপনি প্রতিটি সময় ব্যবহার করার পরিবর্তে [].forEach.call()বা এর পরিবর্তে Array.prototype.forEach.call()এটিকে একটি সাধারণ ফাংশন তৈরি করুন:

function forEach( list, callback ) {
    Array.prototype.forEach.call( list, callback );
}

এখন আপনি আরও জটিল এবং অস্পষ্ট কোডের পরিবর্তে এই ফাংশনটি কল করতে পারেন:

forEach( document.querySelectorAll('a'), function( el ) {
   // whatever with the current node
});

5

এটি ব্যবহার করে আরও ভাল লেখা যেতে পারে

Array.prototype.forEach.call( document.querySelectorAll('a'), function(el) {

});

যা হয় তা হ'ল document.querySelectorAll('a')একটি অ্যারের অনুরূপ একটি বস্তু ফেরত দেয় তবে এটি Arrayধরণের থেকে উত্তরাধিকার সূত্রে আসে না । সুতরাং আমরা অবজেক্ট forEachথেকে পদ্ধতিটিকে Array.prototypeপ্রসঙ্গের সাথে কল করে মান হিসাবে ফিরিয়ে আনিdocument.querySelectorAll('a')


3
[].forEach.call( document.querySelectorAll('a'), function(el) {
   // whatever with the current node
});

এটি মূলত:

var arr = document.querySelectorAll('a');
arr.forEach(function(el) {
   // whatever with the current node
});

2

এই পুরানো প্রশ্নের উপর আপডেট করতে চান:

[].foreach.call()আধুনিক ব্রাউজারগুলিতে উপাদানগুলির সাহায্যে লুপটি ব্যবহার করার কারণটি বেশিরভাগ ক্ষেত্রেই শেষ। আমরা document.querySelectorAll("a").foreach()সরাসরি ব্যবহার করতে পারি ।

নোডলিস্টের অবজেক্টগুলি নোডের সংগ্রহ যা সাধারণত নোড.চাইল্ড নোড এবং ডকুমেন্ট.কোয়ারিসিলেক্টরআল () এর মতো পদ্ধতি দ্বারা ফিরে আসে।

যদিও নোডলিস্ট কোনও অ্যারে নয়, ফোরএচ () দিয়ে এটির উপরে পুনরাবৃত্তি করা সম্ভব । এটি অ্যারে.ফর্ম () ব্যবহার করে একটি আসল অ্যারেতে রূপান্তরিত হতে পারে।

তবে কিছু পুরানো ব্রাউজারগুলি নোডলিস্ট.ফোর (প্রতিটি)) বা অ্যারে.ফ্রোম () প্রয়োগ করে নি। এটি অ্যারে.প্রোটোটাইপ.ফোরেচ () ব্যবহার করে সংঘটিত হতে পারে - এই নথির উদাহরণটি দেখুন।


1

একটি ফাঁকা অ্যারের forEachপ্রোটোটাইপে একটি সম্পত্তি রয়েছে যা একটি ফাংশন অবজেক্ট। (খালি অ্যারে হ'ল forEachসমস্ত Arrayবস্তুর যে ক্রিয়াকলাপটি রয়েছে তার রেফারেন্স পাওয়ার সহজ উপায় )) ফাংশন অবজেক্টগুলির একটি callবৈশিষ্ট্য রয়েছে যা একটি ফাংশন। আপনি যখন কোনও ফাংশনের callফাংশনটি শুরু করেন, এটি প্রদত্ত যুক্তি দিয়ে ফাংশনটি চালায়। প্রথম যুক্তিটি thisডাকা ফাংশনে পরিণত হয়।

আপনি এখানেcall ফাংশন জন্য ডকুমেন্টেশন খুঁজে পেতে পারেন । জন্য ডকুমেন্টেশন হয় এখানেforEach


1

কেবল একটি লাইন যুক্ত করুন:

NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;

ও ভয়েলা!

document.querySelectorAll('a').forEach(function(el) {
  // whatever with the current node
});

উপভোগ করুন :—)

সতর্কতা: নোডলিস্ট একটি বিশ্বব্যাপী শ্রেণি। আপনি যদি পাবলিক লাইব্রেরি লিখেন তবে এই পুনঃসংশোধনটি ব্যবহার করবেন না। তবে আপনি ওয়েবসাইট বা নোড.জেএস অ্যাপে কাজ করার সময় স্ব-কার্যকারিতা বাড়ানোর পক্ষে এটি খুব সুবিধাজনক।


1

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

const forEach = (array, callback) => {
  if (!array || !array.length || !callback) return
  for (var i = 0; i < array.length; i++) {
    callback(array[i], i);
  }
}

forEach(document.querySelectorAll('.a-class'), (item, index) => {
  console.log(`Item: ${item}, index: ${index}`);
});

0

[]সর্বদা একটি নতুন অ্যারে প্রদান করে, এটি সমান new Array()তবে অ্যারে ফেরত দেওয়ার গ্যারান্টিযুক্ত কারণ Arrayব্যবহারকারীর দ্বারা ওভাররাইট করা যেতে পারে যেখানে []পারে না। সুতরাং এটির প্রোটোটাইপ পাওয়ার নিরাপদ উপায় Array, তারপরে বর্ণিত হিসাবে, callঅ্যারেলেক নোডলিস্টের (এটি) ফাংশনটি সম্পাদন করতে ব্যবহৃত হয়।

একটি প্রদত্ত এই মান এবং আর্গুমেন্ট পৃথকভাবে সরবরাহ সঙ্গে একটি ফাংশন কল। MDN


যদিও []ইচ্ছা আসলে সবসময় একটি অ্যারের ফিরে যখন window.Array(সব বয়সী ব্রাউজারে) কিছু দিয়ে ওভাররাইট করা যেতে পারে, তাই খুব করতে window.Array.prototype.forEachকিছু দিয়ে ওভাররাইট হবে। উভয় ক্ষেত্রেই সুরক্ষার কোনও গ্যারান্টি নেই, ব্রাউজারগুলিতে যা গ্রাহকরা / সেটারগুলি বা অবজেক্ট সিলিং / ফ্রিজিং সমর্থন করে না (হিমায়িত করে যার ফলে নিজের নিজের এক্সটেনসিবিলিটি সমস্যা রয়েছে)।
নর্গারগার্ড

মুছে যাওয়ার সম্ভাবনা সংক্রান্ত অতিরিক্ত তথ্য যোগ করার জন্য উত্তর সম্পাদনা করুন মুক্ত মনে prototypeঅথবা এটি এর পদ্ধতি: forEach
Xotic750

0

নরগার্ড কী করেছে [].forEach.call() এবং জেমস আলার্ডাইস ব্যাখ্যা করেছেন যে আমরা এটি কেন করি: কারণ ক্যোয়ারীস্লিেক্টরআল NodeListএমন একটি প্রত্যাবর্তন করে যার জন্য প্রতিটি পদ্ধতি নেই ...

আপনার কাছে ক্রম 51+, ফায়ারফক্স 50+, অপেরা 38, সাফারি 10 এর মতো আধুনিক ব্রাউজার না থাকলে।

যদি না হয় তবে আপনি একটি পলিফিল যোগ করতে পারেন :

if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = function (callback, thisArg) {
        thisArg = thisArg || window;
        for (var i = 0; i < this.length; i++) {
            callback.call(thisArg, this[i], i, this);
        }
    };
}

0

এই পৃষ্ঠায় প্রচুর ভাল তথ্য ( উত্তর + উত্তর + মন্তব্য দেখুন ), তবে আমার কাছে সম্প্রতি ওপি হিসাবে একই প্রশ্ন ছিল এবং পুরো ছবিটি পেতে এটি কিছু খনন করেছে। সুতরাং, এখানে একটি সংক্ষিপ্ত সংস্করণ:

লক্ষ্যটি হ'ল Arrayএকটি অ্যারে-তে এমন পদ্ধতি ব্যবহার NodeListকরা যাতে সেগুলি নিজেই করে না।

একটি পুরানো প্যাটার্ন অ্যারের পদ্ধতিগুলির মাধ্যমে কো-অপ্ট করেছে Function.call()এবং এটি টাইপ করার []চেয়ে Array.prototypeসংক্ষিপ্ত হওয়ার চেয়ে অ্যারে লিটারাল ( ) ব্যবহার করেছে :

[].forEach.call(document.querySelectorAll('a'), a => {})

একটি নতুন প্যাটার্ন (পোস্ট ECMAScript 2015) ব্যবহার করার জন্য Array.from():

Array.from(document.querySelectorAll('a')).forEach(a => {})
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.