লুপগুলির ভিতরে জাভাস্ক্রিপ্ট বন্ধকরণ - সাধারণ ব্যবহারিক উদাহরণ


2814

var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

এটি এটিকে আউটপুট করে:

আমার মান: 3
আমার মান: 3
আমার মান: 3

যেখানে আমি এটি আউটপুট করতে চাই:

আমার মান: 0
আমার মান: 1
আমার মান: 2


ইভেন্ট শ্রোতা ব্যবহার করে যখন ফাংশনটি চালাতে দেরি হয় তখন একই সমস্যা দেখা দেয়:

var buttons = document.getElementsByTagName("button");
// let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
  // as event listeners
  buttons[i].addEventListener("click", function() {
    // each should log its value.
    console.log("My value: " + i);
  });
}
<button>0</button>
<br />
<button>1</button>
<br />
<button>2</button>

… বা অ্যাসিঙ্ক্রোনাস কোড, যেমন প্রতিশ্রুতি ব্যবহার করে:

// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));

for (var i = 0; i < 3; i++) {
  // Log `i` as soon as each promise resolves.
  wait(i * 100).then(() => console.log(i));
}

এই প্রাথমিক সমস্যার সমাধান কী?


55
আপনি যদি নিশ্চিত হন যে আপনি funcsকোনও অ্যারে হতে চান না , আপনি যদি সংখ্যার সূচকগুলি ব্যবহার করেন? শুধু একটি মাথা আপ.
ড্যানমান

23
এটি সত্যিই বিভ্রান্তিকর সমস্যা। এই নিবন্ধটি এটি বুঝতে আমাকে সহায়তা করে । এটি অন্যকেও সহায়তা করতে পারে।
ব্যবহারকারী3199690

4
অন্য একটি সহজ এবং ব্যাখ্যাযুক্ত সমাধান: 1) নেস্টেড ফাংশনগুলির তাদের "উপরে" সুযোগের অ্যাক্সেস রয়েছে ; ২) একটি ক্লোজার সলিউশন ... "ক্লোজার হ'ল প্যারেন্ট ফাংশন বন্ধ হয়ে যাওয়ার পরেও প্যারেন্ট স্কোপে অ্যাক্সেস থাকা একটি ফাংশন"।
পিটার ক্রাউস

2
আরও ভাল আনসারস্ট্যান্ডিং জাভাস্ক্রিপ্ট.এনফো
সৌরভ আহুজা

35
ইন ES6 , একটি তুচ্ছ সমাধান ভেরিয়েবল ডিক্লেয়ার হয় আমি সঙ্গে এলইটি , যা লুপের শরীর থেকে scoped হয়।
টমাস নিকডিম

উত্তর:


2145

ঠিক আছে, সমস্যাটি হ'ল ভেরিয়েবলটি iআপনার প্রতিটি বেনামে ফাংশনের মধ্যে ফাংশনের বাইরে একই ভেরিয়েবলের সাথে আবদ্ধ।

ক্লাসিক সমাধান: বন্ধ

আপনি যা করতে চান তা হ'ল প্রতিটি ফাংশনের মধ্যে ভেরিয়েবলটি ফাংশনের বাইরে আলাদা, অপরিবর্তনীয় মানকে বাঁধতে হয়:

var funcs = [];

function createfunc(i) {
  return function() {
    console.log("My value: " + i);
  };
}

for (var i = 0; i < 3; i++) {
  funcs[i] = createfunc(i);
}

for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

যেহেতু জাভাস্ক্রিপ্টে কোনও ব্লক স্কোপ নেই - কেবলমাত্র ফাংশন স্কোপ - নতুন ফাংশনটিতে ক্রিয়াকলাপটি তৈরি করে মোড় করে, আপনি নিশ্চিত করেন যে "i" এর মান আপনার ইচ্ছার মতোই রয়েছে।


ES5.1 সমাধান: forEach

Array.prototype.forEachফাংশনটির তুলনামূলকভাবে ব্যাপক প্রাপ্যতার সাথে (২০১৫), এটি লক্ষ্য করার মতো যে সেই পরিস্থিতিতেগুলিতে পুনরাবৃত্তির সাথে মূলত মানগুলির একটি অ্যারে জুড়ে জড়িত, .forEach()প্রতিটি পুনরাবৃত্তির জন্য একটি স্বতন্ত্র বন্ধ করার জন্য একটি পরিষ্কার, প্রাকৃতিক উপায় সরবরাহ করে। এটি হ'ল ধরে নিই যে আপনার কাছে মানগুলি (ডিওএম রেফারেন্স, অবজেক্টস, যাই হোক না কেন) রয়েছে এমন কিছু ধরণের অ্যারে পেয়েছেন এবং প্রতিটি উপাদানকে নির্দিষ্ট করে কলব্যাক সেটআপ করার ক্ষেত্রে সমস্যা দেখা দিলে আপনি এটি করতে পারেন:

var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
  // ... code code code for this one element
  someAsynchronousFunction(arrayElement, function() {
    arrayElement.doSomething();
  });
});

ধারণাটি হ'ল .forEachলুপের সাথে ব্যবহৃত কলব্যাক ফাংশনের প্রতিটি অনুরোধটি তার নিজস্ব বন্ধ হয়ে যাবে। সেই হ্যান্ডলারে প্রবেশ করা প্যারামিটারটি পুনরাবৃত্তির সেই নির্দিষ্ট ধাপের সাথে নির্দিষ্ট অ্যারে উপাদান। যদি এটি অ্যাসিক্রোনাস কলব্যাকে ব্যবহৃত হয়, তবে এটি পুনরাবৃত্তির অন্যান্য ধাপে প্রতিষ্ঠিত অন্যান্য কলব্যাকগুলির সাথে সংঘর্ষিত হবে না।

আপনি যদি jQuery এ কাজ করছেন বলে মনে করেন তবে $.each()ফাংশনটি আপনাকে অনুরূপ ক্ষমতা দেয়।


ES6 সমাধান: let

ইসমাস্ক্রিপ্ট ((ইএস)) এমন নতুন letএবং constকীওয়ার্ডগুলির সাথে পরিচয় করিয়েছে যা- varভিত্তিক ভেরিয়েবলগুলির চেয়ে আলাদাভাবে স্কোপ করা হয়। উদাহরণস্বরূপ, একটি letবেসড সূচকযুক্ত একটি লুপে লুপের মাধ্যমে প্রতিটি পুনরাবৃত্তির iলুপ স্কোপ সহ একটি নতুন ভেরিয়েবল থাকবে , সুতরাং আপনার কোডটি আপনার প্রত্যাশা অনুযায়ী কাজ করবে। অনেক সংস্থান আছে, তবে আমি 2ity এর ব্লক-স্কোপিং পোস্টটি সুপারিশ করব তথ্যের উত্স হিসাবে ।

for (let i = 0; i < 3; i++) {
  funcs[i] = function() {
    console.log("My value: " + i);
  };
}

যদিও সাবধান থাকুন যে আইই 9-আইই 11 এবং এজ 14 টি সমর্থন পূর্বে letকিন্তু উপরেরটি ভুলটি পেয়েছেন (তারা iপ্রতিটি সময় নতুন তৈরি করে না , তাই উপরের সমস্ত ফাংশনগুলি 3 ব্যবহার করে যেমন তারা ব্যবহার করত var) log এজ 14 অবশেষে এটি ঠিক আছে।


7
নয় function createfunc(i) { return function() { console.log("My value: " + i); }; }এখনো অবসান হয়েছে কারণ এটি পরিবর্তনশীল ব্যবহার i?
45 レ ッ ク

55
দুর্ভাগ্যক্রমে, এই উত্তরটি পুরানো হয়ে গেছে এবং নীচের অংশে কেউ সঠিক উত্তর দেখতে পাবে না - Function.bind()এখনই সম্ভবত ব্যবহার করা আরও ভাল
ও্লাদিমির পালান্ট

81
@Wladimir: আপনার প্রস্তাবনা যে .bind()হয় "সঠিক উত্তর" ঠিক নয়। তাদের প্রত্যেকের নিজস্ব জায়গা আছে। সঙ্গে .bind()আপনি বাঁধাই ছাড়া আর্গুমেন্ট বাঁধতে পারেন না thisমান। এছাড়াও আপনি iকলগুলির মধ্যে রূপান্তর করার ক্ষমতা ছাড়াই যুক্তিটির একটি অনুলিপি পান যা কখনও কখনও প্রয়োজন হয়। সুতরাং এগুলি একেবারে পৃথক নির্মাণ, উল্লেখ করা উচিত নয় যে .bind()বাস্তবায়নগুলি histor তিহাসিকভাবে ধীর হয়েছে। নিশ্চিত যে সাধারণ উদাহরণে হয় কাজ করবে তবে ক্লোজারগুলি বোঝার জন্য একটি গুরুত্বপূর্ণ ধারণা এবং এটিই প্রশ্নটি ছিল।
কুকি দানব

8
অনুগ্রহ করে ফিরতি ফাংশন হ্যাকগুলি ব্যবহার বন্ধ করুন, পরিবর্তে [] .ফৌচ বা []। ম্যাপ ব্যবহার করুন কারণ তারা একই স্কোপ ভেরিয়েবলগুলি পুনরায় ব্যবহার করা এড়ায়।
ক্রিশ্চিয়ান ল্যান্ডগ্রেন

32
@ ক্রিশ্চিয়ালান ল্যান্ডগ্রেন: এটি কেবল তখনই কার্যকর যখন আপনি কোনও অ্যারের পুনরাবৃত্তি করতে পারেন। এই কৌশলগুলি "হ্যাক" নয়। তারা প্রয়োজনীয় জ্ঞান।

379

চেষ্টা করুন:

var funcs = [];
    
for (var i = 0; i < 3; i++) {
    funcs[i] = (function(index) {
        return function() {
            console.log("My value: " + index);
        };
    }(i));
}

for (var j = 0; j < 3; j++) {
    funcs[j]();
}

সম্পাদনা (2014):

ব্যক্তিগতভাবে আমি মনে করি ব্যবহার সম্পর্কে.bind অস্টের সাম্প্রতিক উত্তরটি এখন এই ধরণের জিনিসটি করার সেরা উপায়। লো-ড্যাশ / আন্ডারস্কোর এরও রয়েছে _.partialযখন আপনার প্রয়োজন হয় না বা bindএর সাথে ঝামেলা করতে চান thisArg


2
সম্পর্কে কোন ব্যাখ্যা }(i));?
aswzen

3
@ আস্জেন আমি মনে করি এটি ফাংশনের iযুক্তি হিসাবে চলেছে index
জেট ব্লু

এটি আসলে স্থানীয় পরিবর্তনশীল সূচক তৈরি করছে।
অভিষেক সিং

1
তাত্ক্ষণিকভাবে ফাংশন এক্সপ্রেশন, ওরফে আইআইএফই vo (i) বেনামে ফাংশন প্রকাশের যুক্তি যা অবিলম্বে ডাকা হয় এবং সূচি i থেকে সেট হয়ে যায় i
ডিম

348

অন্য উপায় যা এখনও উল্লেখ করা হয়নি তা হ'ল ব্যবহার Function.prototype.bind

var funcs = {};
for (var i = 0; i < 3; i++) {
  funcs[i] = function(x) {
    console.log('My value: ' + x);
  }.bind(this, i);
}
for (var j = 0; j < 3; j++) {
  funcs[j]();
}

হালনাগাদ

@ স্পিন্ট এবং @ মেকদেব দ্বারা চিহ্নিত হিসাবে আপনি প্রথমে লুপের বাইরে ফাংশনটি তৈরি করে এবং তারপরে ফলাফলগুলি লুপের সাথে আবদ্ধ করে আপনি আরও ভাল পারফরম্যান্স পাবেন।

function log(x) {
  console.log('My value: ' + x);
}

var funcs = [];

for (var i = 0; i < 3; i++) {
  funcs[i] = log.bind(this, i);
}

for (var j = 0; j < 3; j++) {
  funcs[j]();
}


আমি এই দিনগুলিতেও এটি করি, আমি ল-ড্যাশ / আন্ডারস্কোরও পছন্দ করি_.partial
বিজোর

17
.bind()ECMAScript 6 টি বৈশিষ্ট্য সহ বৃহত্তরভাবে অপ্রচলিত হবে। তদতিরিক্ত, এটি আসলে পুনরাবৃত্তির জন্য দুটি ফাংশন তৈরি করে। প্রথমে বেনামে, তারপরে তৈরি হওয়া .bind()। লুপের বাইরে এটি তৈরি করার পরে আরও ভাল ব্যবহার .bind()

5
@ স্পিন্ট @ মেকদেব - আপনি উভয়ই সঠিক। আমার প্রাথমিক উদাহরণটি কীভাবে bindব্যবহৃত হয় তা প্রদর্শনের জন্য দ্রুত লেখা হয়েছিল । আপনার পরামর্শ অনুসারে আমি আরও একটি উদাহরণ যুক্ত করেছি।
অস্ট

5
আমি মনে করি যে দুটি ও (এন) লুপের তুলনায় গণনা নষ্ট করার পরিবর্তে (var i = 0; i <3; i ++) {লগ ক্যাল (এটি, আমি); }
ব্যবহারকারী 2290820

1
.bind () গৃহীত উত্তর PLUS ফিডলগুলি যা বোঝায় সেটিকে করে this
নিড়ানি

269

তাত্ক্ষণিকভাবে আমন্ত্রিত ফাংশন এক্সপ্রেশন ব্যবহার করে , সূচক ভেরিয়েবলটি বন্ধ করার সহজতম এবং সর্বাধিক পঠনযোগ্য উপায়:

for (var i = 0; i < 3; i++) {

    (function(index) {

        console.log('iterator: ' + index);
        //now you can also loop an ajax call here 
        //without losing track of the iterator value:   $.ajax({});
    
    })(i);

}

এটি পুনরাবৃত্তিকারীকে iবেনামি ফাংশনে প্রেরণ করে যা আমরা হিসাবে সংজ্ঞায়িত করি index। এটি একটি ক্লোজার তৈরি করে, যেখানে ভেরিয়েবল iIIFE এর মধ্যে যে কোনও অ্যাসিনক্রোনাস কার্যকারিতা পরে ব্যবহারের জন্য সংরক্ষণ করা হবে saved


10
আরও কোড পঠনযোগ্যতা এবং বিভ্রান্তি এড়াতে iকোনটি, আমি ফাংশনটির প্যারামিটারটির নামকরণ করব index
কাইল ফ্যালকোনার

5
মূল প্রশ্নে বর্ণিত অ্যারে ফানকগুলি সংজ্ঞায়িত করতে আপনি এই কৌশলটি কীভাবে ব্যবহার করবেন ?
নিকো

একই উপায় হিসেবে মূল প্রশ্ন দেখানো @Nico ছাড়া আপনি ব্যবহার করেন indexপরিবর্তে i
JLRishe

@ জেএলআরিশvar funcs = {}; for (var i = 0; i < 3; i++) { funcs[i] = (function(index) { return function() {console.log('iterator: ' + index);}; })(i); }; for (var j = 0; j < 3; j++) { funcs[j](); }
নিকো

1
@Nico উপ এর নির্দিষ্ট ক্ষেত্রে, তারা শুধু সংখ্যার উপর iterating করছি, তাই এই একটি মহান ক্ষেত্রে হবে না .forEach(), কিন্তু অনেক সময়, যখন এক একটি অ্যারের সঙ্গে বন্ধ শুরু হয়, forEach()একটি ভাল পছন্দ মত হল:var nums [4, 6, 7]; var funcs = {}; nums.forEach(function (num, i) { funcs[i] = function () { console.log(num); }; });
জেএলরিশ

163

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

সুতরাং অন্য অনেকে উল্লিখিত হিসাবে, সমস্যাটি হ'ল অভ্যন্তরীণ ফাংশনটি একই iভেরিয়েবলটি উল্লেখ করে । সুতরাং কেন আমরা কেবল প্রতিটি পুনরাবৃত্তির জন্য একটি নতুন স্থানীয় পরিবর্তনশীল তৈরি করি না, এবং এর পরিবর্তে অভ্যন্তরীণ ফাংশন রেফারেন্স রাখি?

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    var ilocal = i; //create a new local variable
    funcs[i] = function() {
        console.log("My value: " + ilocal); //each should reference its own local variable
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

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

দেখা যাচ্ছে, এটাই সমস্যা। প্রতিটি পুনরাবৃত্তি একই সুযোগ ভাগ করে নিচ্ছে, তাই প্রথমটির পরে প্রতিটি পুনরাবৃত্তি কেবল ওভাররাইট করা ilocalএমডিএন থেকে :

গুরুত্বপূর্ণ: জাভাস্ক্রিপ্টের ব্লক স্কোপ নেই। একটি ব্লকের সাথে প্রবর্তিত ভেরিয়েবলগুলি সমন্বিত ফাংশন বা স্ক্রিপ্টের জন্য স্কোপ করা হয় এবং সেগুলি নির্ধারণের প্রভাবগুলি ব্লকের বাইরেও বহাল থাকে। অন্য কথায়, ব্লক স্টেটমেন্টগুলি কোনও সুযোগ প্রবর্তন করে না। যদিও "স্ট্যান্ডেলোন" ব্লকগুলি বৈধ বাক্য গঠন, তবে আপনি জাভাস্ক্রিপ্টে স্ট্যান্ডেলোন ব্লক ব্যবহার করতে চান না, কারণ তারা সি বা জাভাতে এই জাতীয় ব্লকের মতো কিছু করেন বলে আপনি মনে করেন তারা যা করেন তা তারা করেন না।

জোর দেওয়ার জন্য পুনরাবৃত্তি:

জাভাস্ক্রিপ্টের ব্লক স্কোপ নেই। একটি ব্লকের সাথে প্রবর্তিত ভেরিয়েবলগুলি সমন্বিত ফাংশন বা স্ক্রিপ্টের জন্য স্কোপ করা হয়

আমরা ilocalপ্রতিটি পুনরাবৃত্তিতে এটি ঘোষণার আগে এটি পরীক্ষা করে দেখতে পারি:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
  console.log(ilocal);
  var ilocal = i;
}

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

বন্ধ

এর অর্থ হ'ল অভ্যন্তরীণ ফাংশনগুলি বাইরের ভেরিয়েবলগুলিকে "ধরে" রাখে এবং তাদের জীবিত রাখবে, এমনকি যদি বাহ্যিক ক্রিয়াটি ফিরে আসে। এটি ব্যবহার করতে, আমরা একটি নতুন সুযোগ তৈরি করতে, নতুন স্কোপে ঘোষণা করতে ilocalএবং একটি অভ্যন্তরীণ ফাংশন যা ব্যবহার করে ilocal(নীচে আরও ব্যাখ্যা) ফিরিয়ে আনতে খাঁটিভাবে একটি মোড়ক ফাংশন তৈরি এবং কল করি

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = (function() { //create a new scope using a wrapper function
        var ilocal = i; //capture i into a local var
        return function() { //return the inner function
            console.log("My value: " + ilocal);
        };
    })(); //remember to run the wrapper function
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}

একটি মোড়ক ফাংশনের অভ্যন্তরীণ ফাংশন তৈরি করা অভ্যন্তরীণ ফাংশনটিকে একটি ব্যক্তিগত পরিবেশ দেয় যা কেবল এটি "অ্যাক্সেস" অ্যাক্সেস করতে পারে। সুতরাং, প্রতিবার আমরা যখন র‍্যাপার ফাংশনটি বলি তখন আমরা তার নিজস্ব পৃথক পরিবেশের সাথে একটি নতুন অভ্যন্তরীণ ফাংশন তৈরি করি, এটি নিশ্চিত করে যে ilocalভেরিয়েবলগুলি একে অপরের সাথে সংঘর্ষ না হয় এবং এটি ওভাররাইট করে। কয়েকটি অন্যান্য ছোট্ট অপ্টিমাইজেশন চূড়ান্ত উত্তর দেয় যা অন্য অনেক এসও ব্যবহারকারীরা দিয়েছেন:

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (var i = 0; i < 3; i++) {
    funcs[i] = wrapper(i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();
}
//creates a separate environment for the inner function
function wrapper(ilocal) {
    return function() { //return the inner function
        console.log("My value: " + ilocal);
    };
}

হালনাগাদ

ES6 এখন মূলধারার সাথে, আমরা এখন letব্লক-স্কোপড ভেরিয়েবলগুলি তৈরি করতে নতুন কীওয়ার্ডটি ব্যবহার করতে পারি :

//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};

var funcs = {};
for (let i = 0; i < 3; i++) { // use "let" to declare "i"
    funcs[i] = function() {
        console.log("My value: " + i); //each should reference its own local variable
    };
}
for (var j = 0; j < 3; j++) { // we can use "var" here without issue
    funcs[j]();
}

দেখুন এখন কত সহজ! আরও তথ্যের জন্য এই উত্তরটি দেখুন , যা আমার তথ্য ভিত্তিক।


আমি পছন্দ করি আপনি কীভাবে আইআইএফই উপায়টি ব্যাখ্যা করেছেন। আমি এটি খুঁজছিলাম। ধন্যবাদ.
ক্যাপচারড্রি

4
এখন জাভাস্ক্রিপ্ট ব্লক scoping ব্যবহার যেমন একটি জিনিস letএবং constকীওয়ার্ড। যদি এই উত্তরটি অন্তর্ভুক্ত করতে প্রসারিত হয় তবে এটি আমার মতে বিশ্বব্যাপী আরও কার্যকর হবে useful

@TinyGiant নিশ্চিত জিনিস, আমি কিছু তথ্য যুক্ত করেছি letএবং আরও সম্পূর্ণ ব্যাখ্যা যুক্ত করেছি
woojoo666

@ woojoo666 আপনার উত্তর দুটি পর্যায়ক্রমে URL টি কলিং জন্য কাজ এত মত একটি লুপ আছে যায়নি: i=0; while(i < 100) { setTimeout(function(){ window.open("https://www.bbc.com","_self") }, 3000); setTimeout(function(){ window.open("https://www.cnn.com","_self") }, 3000); i++ }? (উইন্ডো ওপেন () কে জেটলেটিনবিডের সাথে প্রতিস্থাপন করতে পারে ......)
বাদামি

এই জাতীয় উত্তর সম্পর্কে দুঃখিত আপনার উদাহরণের কোডটি ইতিমধ্যে কাজ করে বলে মনে হচ্ছে না। আপনি iআপনার টাইমআউট ফাংশনগুলিতে ব্যবহার করছেন না , সুতরাং আপনার কোনও বন্ধের দরকার নেই
woojoo666

151

ES6 এখন ব্যাপকভাবে সমর্থিত, এই প্রশ্নের সেরা উত্তর পরিবর্তিত হয়েছে। ES6 এই সঠিক পরিস্থিতিতে জন্য কীওয়ার্ড letএবং সরবরাহ করে const। ক্লোজারগুলির সাথে ঘোরাঘুরি করার পরিবর্তে আমরা কেবল letএই জাতীয় লুপ স্কোপ ভেরিয়েবল সেট করতে ব্যবহার করতে পারি :

var funcs = [];

for (let i = 0; i < 3; i++) {          
    funcs[i] = function() {            
      console.log("My value: " + i); 
    };
}

valতারপরে এমন কোনও বস্তুর দিকে নির্দেশ করবে যা লুপটির সেই নির্দিষ্ট মোড়ের সাথে সুনির্দিষ্ট এবং অতিরিক্ত ক্লোজার স্বরলিপি ব্যতীত সঠিক মানটি ফিরিয়ে দেবে। এটি স্পষ্টতই এই সমস্যাটিকে সহজতর করে তোলে।

constletঅতিরিক্ত নিষেধাজ্ঞার সাথে সমান যা ভেরিয়েবলের নামটি প্রাথমিক নিয়োগের পরে কোনও নতুন রেফারেন্সে প্রত্যাবর্তন করতে পারে না।

ব্রাউজারগুলির সর্বশেষতম সংস্করণগুলিকে লক্ষ্য করে তাদের জন্য এখন ব্রাউজার সমর্থন support const/ letবর্তমানে সর্বশেষতম ফায়ারফক্স, সাফারি, এজ এবং ক্রোমে সমর্থিত। এটি নোডেও সমর্থিত এবং আপনি বাবেলের মতো বিল্ড সরঞ্জামগুলির সুবিধা নিয়ে এটি যে কোনও জায়গায় ব্যবহার করতে পারেন। আপনি এখানে একটি কাজের উদাহরণ দেখতে পারেন: http://jsfiddle.net/ben336/rbU4t/2/

ডক্স এখানে:

যদিও সাবধান থাকুন যে আইই 9-আইই 11 এবং এজ 14 টি সমর্থন পূর্বে letকিন্তু উপরেরটি ভুলটি পেয়েছেন (তারা iপ্রতিটি সময় নতুন তৈরি করে না , তাই উপরের সমস্ত ফাংশনগুলি 3 ব্যবহার করে যেমন তারা ব্যবহার করত var) log এজ 14 অবশেষে এটি ঠিক আছে।


দুর্ভাগ্যক্রমে, 'লেট' এখনও পুরোপুরি সমর্থিত নয়, বিশেষত মোবাইলে। বিকাশকারী.মোজিলা.আর.ইন-
ইউএস

2
জুন '16 এর হিসাবে, আসুন আইওএস সাফারি, অপেরা মিনি এবং সাফারি 9. ব্যতীত সমস্ত বড় ব্রাউজার সংস্করণে সমর্থিত Ever চিরসবুজ ব্রাউজারগুলি এটি সমর্থন করে। উচ্চ কম্পাইলেন্সী মোডটি চালু না করে প্রত্যাশিত আচরণটি রাখতে বাবেল এটি সঠিকভাবে স্থানান্তর করবে।
ড্যান প্যান্ট্রি

@ ড্যানপ্যান্ট্রি হ্যাঁ একটি আপডেটের জন্য সময় সম্পর্কে :) কনস্ট, ডক লিঙ্ক এবং আরও ভাল সামঞ্জস্যতার তথ্যের উল্লেখ সহ আরও ভালভাবে বর্তমানের পরিস্থিতি প্রতিফলিত করার জন্য আপডেট হয়েছে।
বেন ম্যাককর্মিক

আমরা কেন আমাদের কোডটি ট্রিলিপল করতে বাবেল ব্যবহার করি না তাই ES6 / 7 সমর্থন করে না এমন ব্রাউজারগুলি কী হচ্ছে তা বুঝতে পারে?
পিক্সেল 67

87

এটি বলার আর একটি উপায় এটি i আপনার ফাংশনটি ফাংশনটি সম্পাদন করার সময় সীমাবদ্ধ, ফাংশন তৈরির সময় নয়।

আপনি যখন ক্লোজার তৈরি করবেন, i বাইরের স্কোপে সংজ্ঞায়িত ভেরিয়েবলের একটি রেফারেন্স অনুলিপি নয়। এটি কার্যকর করার সময় মূল্যায়ন করা হবে।

অন্যান্য উত্তরগুলির বেশিরভাগই অন্য ভেরিয়েবল তৈরি করে কাজ করার উপায় সরবরাহ করে যা আপনার জন্য মান পরিবর্তন করবে না।

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


71

জাভাস্ক্রিপ্টে ভেরিয়েবলের সুযোগটি আপনাকে যা বোঝার দরকার তা হ'ল ফাংশনের উপর ভিত্তি করে। সি # বলার চেয়ে এটি একটি গুরুত্বপূর্ণ পার্থক্য যেখানে আপনার ব্লক স্কোপ রয়েছে এবং কেবল ভেরিয়েবলের অনুলিপি করার জন্য এটির অভ্যন্তরের কোনওটিতে কাজ করবে।

এটিকে এমন কোনও ফাংশনে মুড়িয়ে ফেলা যা অ্যাপ্যাকার এর উত্তরের মতো ফাংশনটি ফিরিয়ে দেওয়ার মূল্যায়ন করে তা কৌশলটি করবে, কারণ ভেরিয়েবলের এখন ফাংশনের সুযোগ রয়েছে।

ভেরার পরিবর্তে একটি লেট কীওয়ার্ডও রয়েছে যা ব্লক স্কোপ বিধিটি ব্যবহারের অনুমতি দেয়। সেক্ষেত্রে জন্য ভেরিয়েবলের সংজ্ঞা দেওয়া কৌতুকটি করবে। এটি বলেছে যে লেট কীওয়ার্ডটি সামঞ্জস্যতার কারণে ব্যবহারিক সমাধান নয়।

var funcs = {};

for (var i = 0; i < 3; i++) {
  let index = i; //add this
  funcs[i] = function() {
    console.log("My value: " + index); //change to the copy
  };
}

for (var j = 0; j < 3; j++) {
  funcs[j]();
}


@ নিকফ কোন ব্রাউজার? যেমনটি আমি বলেছি, এটির সাথে সামঞ্জস্যের সমস্যা রয়েছে, এর সাথে আমার বোঝানো হয়েছে গুরুতর সামঞ্জস্যতা সমস্যাগুলি, যেমন আমি মনে করি না যে আসুন আইআই-তে সমর্থনযোগ্য।
eglasius

1
@ নিকফ হ্যাঁ, এই রেফারেন্সটি দেখুন: ডেভেলপার.মোজিলা.আর.ইউ / নতুন_ইন_জাভা স্ক্রিপ্ট _1..7 ... লেট সংজ্ঞা বিভাগটি পরীক্ষা করুন, একটি লুপের ভিতরে একটি
অন্লিক

2
@ নিকফ এইচএমএম, আসলে আপনাকে স্পষ্টভাবে সংস্করণটি নির্দিষ্ট করতে হবে: <স্ক্রিপ্ট টাইপ = "অ্যাপ্লিকেশন / জাভাস্ক্রিপ্ট; সংস্করণ = 1.7" /> ... আইই নিষেধাজ্ঞার কারণে আমি আসলে এটি অন্য কোথাও ব্যবহার করি নি, এটি ঠিক নেই ব্যবহারিক :(
এগ্লাসিয়াস

আপনি এখানে বিভিন্ন সংস্করণগুলির জন্য ব্রাউজার সমর্থন দেখতে পারেন es.wikedia.org/wiki/ জাভাস্ক্রিপ্ট
eglasius


59

এখানে প্রযুক্তির অন্য একটি বৈকল্পিকতা রয়েছে, এটি বজর্নের (অ্যাপ্যাকার) এর অনুরূপ, যা আপনাকে প্যারামিটার হিসাবে পাস করার পরিবর্তে ফাংশনের অভ্যন্তরে ভেরিয়েবলের মান নির্ধারণ করতে দেয় যা কখনও কখনও পরিষ্কার হতে পারে:

var funcs = [];
for (var i = 0; i < 3; i++) {
    funcs[i] = (function() {
        var index = i;
        return function() {
            console.log("My value: " + index);
        }
    })();
}

মনে রাখবেন যে আপনি যে কৌশলটিই ব্যবহার করুন না কেন, indexভেরিয়েবলটি অভ্যন্তরীণ ফাংশনের রিটার্ন কপির সাথে আবদ্ধ, এক ধরণের স্থিতিশীল ভেরিয়েবল হয়ে যায়। অর্থাৎ, এর মান পরিবর্তনগুলি কলগুলির মধ্যে সংরক্ষণ করা হয়। এটি খুব সহজ হতে পারে।


ধন্যবাদ এবং আপনার সমাধান কাজ করে। তবে আমি জিজ্ঞাসা করতে চাই কেন এটি কাজ করে তবে varলাইন এবং লাইনটি অদলবদল করে returnনা? ধন্যবাদ!
মিডনাইট

@ মিডনাইট যদি আপনি অদলবদল করে থাকেন varএবং returnতারপরে অভ্যন্তরীণ ফাংশনটি ফিরে আসার আগে পরিবর্তনশীল বরাদ্দ করা হবে না।
বোয়ান

53

এটি জাভাস্ক্রিপ্টে ক্লোজারগুলি ব্যবহার করে সাধারণ ভুল বর্ণনা করে।

একটি ফাংশন একটি নতুন পরিবেশকে সংজ্ঞায়িত করে

বিবেচনা:

function makeCounter()
{
  var obj = {counter: 0};
  return {
    inc: function(){obj.counter ++;},
    get: function(){return obj.counter;}
  };
}

counter1 = makeCounter();
counter2 = makeCounter();

counter1.inc();

alert(counter1.get()); // returns 1
alert(counter2.get()); // returns 0

প্রতিটি সময় makeCounterজন্য অনুরোধ করা হয়, {counter: 0}ফলাফল একটি নতুন অবজেক্ট তৈরি করা হয়। এছাড়াও, obj নতুন অবজেক্টের রেফারেন্সের জন্য একটি নতুন কপি তৈরি করা হয়েছে। এইভাবে, counter1এবংcounter2 একে অপরের থেকে স্বাধীন।

লুপগুলিতে বন্ধ হওয়া

একটি লুপে একটি ক্লোজার ব্যবহার করা মুশকিল।

বিবেচনা:

var counters = [];

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = {
      inc: function(){obj.counter++;},
      get: function(){return obj.counter;}
    }; 
  }
}

makeCounters(2);

counters[0].inc();

alert(counters[0].get()); // returns 1
alert(counters[1].get()); // returns 1

লক্ষ করুন যে, counters[0]এবং counters[1]হয় না স্বাধীন। আসলে, তারা একই কাজ করেobj !

এটি কারণ objলুপের সমস্ত পুনরাবৃত্তির জুড়ে কেবলমাত্র একটি অনুলিপি রয়েছে , সম্ভবত পারফরম্যান্সের কারণে। যদিও {counter: 0}প্রতিটি পুনরাবৃত্তিতে একটি নতুন অবজেক্ট তৈরি করা হয়, একই কপিobj কেবলমাত্র নতুন অবজেক্টের রেফারেন্স সহ আপডেট হবে।

সমাধানটি হ'ল অন্য সহায়ক ফাংশনটি ব্যবহার করা:

function makeHelper(obj)
{
  return {
    inc: function(){obj.counter++;},
    get: function(){return obj.counter;}
  }; 
}

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = makeHelper(obj);
  }
}

এটি কাজ করে কারণ ফাংশন স্কোপটিতে স্থানীয় ভেরিয়েবলগুলি পাশাপাশি ফাংশন আর্গুমেন্ট ভেরিয়েবলগুলি প্রবেশের পরে নতুন কপি বরাদ্দ করা হয়।


ছোট স্পষ্টকরণ: লুপগুলিতে বন্ধের প্রথম উদাহরণে, কাউন্টারগুলি [0] এবং কাউন্টারগুলি [1] পারফরম্যান্সের কারণে নয় তবে স্বাধীন নয়। কারণটি হ'ল যে var obj = {counter: 0};কোনও কোড কার্যকর করার আগে মূল্যায়িত হয়: এমডিএন বর্ণ : বর্ণ ঘোষণাগুলি যেখানেই ঘটে সেখানে কোনও কোড কার্যকর করার আগে প্রক্রিয়াজাত করা হয় before
চারিদিমোস

50

সবচেয়ে সহজ সমাধানটি হ'ল,

পরিবর্তে ব্যবহার করুন:

var funcs = [];
for(var i =0; i<3; i++){
    funcs[i] = function(){
        alert(i);
    }
}

for(var j =0; j<3; j++){
    funcs[j]();
}

যা "2" কে 3 বার সতর্ক করে। এটি কারণ অজানা ফাংশনগুলি লুপের জন্য তৈরি করা হয়, একই সমাপ্তি ভাগ করে, এবং সেই সমাপ্তিতে, মান iএকই হয়। ভাগ করা বন্ধ হওয়া রোধ করতে এটি ব্যবহার করুন:

var funcs = [];
for(var new_i =0; new_i<3; new_i++){
    (function(i){
        funcs[i] = function(){
            alert(i);
        }
    })(new_i);
}

for(var j =0; j<3; j++){
    funcs[j]();
}

এর পিছনে ধারণাটি হ'ল, আইওএফই (তাত্ক্ষণিকভাবে-আহ্বানিত ফাংশন এক্সপ্রেশন) দিয়ে ফোনের লুপটির পুরো শরীরকে আবদ্ধ করে new_iএবং প্যারামিটার হিসাবে পাস করে এবং এটি ক্যাপচার করে i। যেহেতু বেনামে ফাংশনটি তাত্ক্ষণিকভাবে কার্যকর করা হয়, iবেনাম ফাংশনের অভ্যন্তরে সংজ্ঞায়িত প্রতিটি ফাংশনের জন্য মান আলাদা।

এই সমাধানটি এ জাতীয় যে কোনও সমস্যার সাথে খাপ খায় কারণ এটি এই সমস্যাটি ভুগছে মূল কোডটিতে ন্যূনতম পরিবর্তন প্রয়োজন। আসলে, এটি ডিজাইনের মাধ্যমে, এটি কোনও বিষয় হওয়া উচিত নয়!


2
একটি বই একবার অনুরূপ কিছু পড়ুন। আমি এটিও পছন্দ করি, যেহেতু আপনাকে আপনার বিদ্যমান কোডটি (যত বেশি) স্পর্শ করতে হবে না এবং এটি স্পষ্ট হয়ে যায় আপনি কেন এটি করেছিলেন, একবার আপনি যখন স্ব-কলিং ফাংশন প্যাটার্নটি শিখে ফেলেছেন: সদ্য তৈরিতে সেই পরিবর্তনশীলটিকে ফাঁদে ফেলতে সুযোগ।
ড্যানমান

1
@ ড্যানম্যান ধন্যবাদ জাভাস্ক্রিপ্টের ব্লক স্তরের পরিবর্তনশীল সুযোগের অভাব মোকাবেলা করার জন্য সেলফ অজ্ঞাতনামা ফাংশনগুলি খুব ভাল উপায়।
কমল দাğ

3
স্ব-কলিং বা স্ব-আহ্বান করা এই কৌশলটির জন্য উপযুক্ত শব্দ নয়, আইআইএফই (তাত্ক্ষণিকভাবে আমন্ত্রণযুক্ত ফাংশন এক্সপ্রেশন) আরও সঠিকভাবে। তথ্যসূত্র
ঝেরাক্স

31

এই সংক্ষিপ্ত চেষ্টা করুন

  • কোন অ্যারে

  • লুপ জন্য কোন অতিরিক্ত


for (var i = 0; i < 3; i++) {
    createfunc(i)();
}

function createfunc(i) {
    return function(){console.log("My value: " + i);};
}

http://jsfiddle.net/7P6EN/


1
আপনার সমাধানটি আউটপুট সঠিক বলে মনে হচ্ছে তবে এটি অনিবার্যভাবে ফাংশন ব্যবহার করে, কেন কেবল আউটপুটটি কনসোল করে না? মূল প্রশ্নটি বেনামে ফাংশন তৈরি সম্পর্কে যা একইভাবে বন্ধ রয়েছে। সমস্যাটি ছিল, যেহেতু তাদের একক বন্ধ রয়েছে তাই তাদের মান প্রতিটির জন্য একই রকম i আমি আশা করি আপনি এটি পেয়েছেন।
কমল দাğ

30

এখানে একটি সহজ সমাধান যা ব্যবহার করে forEach(আইই 9 তে ফিরে কাজ করে):

var funcs = [];
[0,1,2].forEach(function(i) {          // let's create 3 functions
    funcs[i] = function() {            // and store them in funcs
        console.log("My value: " + i); // each should log its value.
    };
})
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

ছাপে:

My value: 0
My value: 1
My value: 2

27

ওপি দ্বারা প্রদর্শিত কোডের সাথে মুখ্য বিষয়টি iহ'ল দ্বিতীয় লুপ পর্যন্ত কখনও পড়া হয় না। প্রদর্শনের জন্য, কোডটির ভিতরে কোনও ত্রুটি দেখে কল্পনা করুন

funcs[i] = function() {            // and store them in funcs
    throw new Error("test");
    console.log("My value: " + i); // each should log its value.
};

funcs[someIndex]কার্যকর না হওয়া পর্যন্ত ত্রুটি আসলে ঘটে না ()। এই একই যুক্তি ব্যবহার করে, এটি স্পষ্ট হওয়া উচিত যে এর iবিন্দুটি না হওয়া পর্যন্ত এর মানও সংগ্রহ করা হয় না। আসল লুপটি শেষ হয়ে গেলে শর্তটি ব্যর্থ হয় এবং লুপ শেষ হয় যার মান i++দেয় ito এই সময়ে, হয় এবং তাই কখন ব্যবহৃত হয়, এবং মূল্যায়ন করা হয়, এটি 3 - প্রতিবার।3i < 3i3funcs[someIndex]()i

এটি পাস করার জন্য, iএটির মুখোমুখি হওয়ার সাথে সাথে অবশ্যই মূল্যায়ন করতে হবে । নোট করুন যে এটি ইতিমধ্যে আকারে ঘটেছেfuncs[i] (যেখানে 3 টি অনন্য সূচক রয়েছে) । এই মানটি ক্যাপচার করার বিভিন্ন উপায় রয়েছে। একটি হ'ল এটি ইতিমধ্যে এখানে বেশ কয়েকটি উপায়ে প্রদর্শিত একটি ফাংশনটির পরামিতি হিসাবে প্রবেশ করা।

আরেকটি বিকল্প হ'ল একটি ফাংশন অবজেক্ট তৈরি করা যা ভেরিয়েবলটি বন্ধ করতে সক্ষম হবে। এইভাবে সম্পাদন করা যেতে পারে

jsFiddle Demo

funcs[i] = new function() {   
    var closedVariable = i;
    return function(){
        console.log("My value: " + closedVariable); 
    };
};

23

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

var funcs = []

for (var i = 0; i < 3; i += 1) {
  funcs[i] = function () {
    console.log(i)
  }
}

for (var k = 0; k < 3; k += 1) {
  funcs[k]()
}

উপরের অ্যারের প্রতিটি ফাংশন বিশ্বব্যাপী স্কোপ বন্ধ করে দেয় (বিশ্বব্যাপী, কেবল কারণ এটি তাদের ঘোষিত ক্ষেত্র হিসাবে ঘটে)।

পরে এই ফাংশনগুলি iবিশ্বব্যাপী সুযোগের সর্বাধিক বর্তমান মান লগিংয়ের জন্য অনুরোধ করা হয় । এটি হ'ল ম্যাজিক এবং হতাশার বন্ধ।

"জাভাস্ক্রিপ্ট ফাংশনগুলি তাদের ঘোষিত সুযোগের কাছাকাছি চলে যায় এবং সেই সুযোগ পরিবর্তনের অভ্যন্তরে পরিবর্তনশীল মান হিসাবেও সেই সুযোগে অ্যাক্সেস ধরে রাখে।"

letপরিবর্তে ব্যবহার করে varপ্রতিবার forলুপটি সঞ্চালন করে একটি নতুন স্কোপ তৈরি করে প্রতিটি ফাংশনটি বন্ধ হয়ে যাওয়ার জন্য পৃথক সুযোগ তৈরি করে। অন্যান্য বিভিন্ন কৌশল অতিরিক্ত ফাংশন সহ একই জিনিস করে।

var funcs = []

for (let i = 0; i < 3; i += 1) {
  funcs[i] = function () {
    console.log(i)
  }
}

for (var k = 0; k < 3; k += 1) {
  funcs[k]()
}

( letতোলে ভেরিয়েবল scoped ব্লক। ব্লক কোঁকড়া ধনুর্বন্ধনী দ্বারা প্রকাশ করা হয়, কিন্তু লুপ আরম্ভের পরিবর্তনশীল জন্য, ক্ষেত্রে iআমাদের ক্ষেত্রে, ধনুর্বন্ধনী ঘোষণা বলে মনে করা হয়।)


1
আমি এই উত্তরটি না পড়া পর্যন্ত আমি এই ধারণাটি বোঝার জন্য সংগ্রাম করেছি। এটি একটি সত্যই গুরুত্বপূর্ণ পয়েন্টকে স্পর্শ করে - এর মান iবিশ্বব্যাপী সুযোগে সেট করা হচ্ছে। যখন forলুপটি চলমান শেষ করে, এর গ্লোবাল মানi (ব্যবহার করে, বলে এখন অতএব 3. যখনই যে ফাংশন অ্যারের মধ্যে প্রার্থনা করা হয় funcs[j]), iযে ফাংশন বৈশ্বিক উল্লেখ করছে iপরিবর্তনশীল (যা 3)।
Modermo

13

বিভিন্ন সমাধান পড়ার পরে, আমি যুক্ত করতে চাই যে এই সমাধানগুলির কাজটি স্কোপ চেইনের ধারণার উপর নির্ভর করা । এটি জাভাস্ক্রিপ্ট কার্যকর করার সময় কোনও পরিবর্তনকে সমাধান করার উপায়।

  • প্রতিটি ফাংশন সংজ্ঞা সমস্ত স্থানীয় ভেরিয়েবল varএবং এর দ্বারা ঘোষিত একটি স্কোপ তৈরি করে arguments
  • যদি আমাদের অন্য (বহিরাগত) ফাংশনের অভ্যন্তরীণ ফাংশন সংজ্ঞায়িত হয় তবে এটি একটি শৃঙ্খলা তৈরি করে এবং কার্যকর করার সময় এটি ব্যবহার করা হবে
  • যখন কোনও ফাংশন কার্যকর হয়, রানটাইম স্কোপ চেইনে অনুসন্ধান করে ভেরিয়েবলগুলি মূল্যায়ন করে । যদি কোনও ভেরিয়েবল শৃঙ্খলার নির্দিষ্ট বিন্দুতে পাওয়া যায় তবে এটি অনুসন্ধান করা এবং এটি ব্যবহার বন্ধ করে দেবে, অন্যথায় এটি বিশ্বব্যাপী পরিধিটি পৌঁছে না দেওয়া অবধি অবধি অবধি চলতে থাকবে window

প্রাথমিক কোডে:

funcs = {};
for (var i = 0; i < 3; i++) {         
  funcs[i] = function inner() {        // function inner's scope contains nothing
    console.log("My value: " + i);    
  };
}
console.log(window.i)                  // test value 'i', print 3

কখন funcs কার্যকর করা হবে, স্কোপ চেইন হবে function inner -> global। যেহেতু ভেরিয়েবলটি iখুঁজে পাওয়া যায় না function inner( varতর্ক হিসাবে ব্যবহার হিসাবে ঘোষিত বা পাস হয় না), এটি অনুসন্ধান অব্যাহত রাখে, যতক্ষণ না iঅবশেষে বৈশ্বিক ক্ষেত্রের মান খুঁজে পাওয়া যায় window.i

এটি একটি বাহ্যিক কার্যক্রমে মোড়ানো দ্বারা স্পষ্টভাবে একটি সহায়ক ফাংশন সংজ্ঞায়িত করুন harto করেনি বা একটি বেনামী ফাংশন ব্যবহার মত বিয়ন্সের যা করেছে:

funcs = {};
function outer(i) {              // function outer's scope contains 'i'
  return function inner() {      // function inner, closure created
   console.log("My value: " + i);
  };
}
for (var i = 0; i < 3; i++) {
  funcs[i] = outer(i);
}
console.log(window.i)          // print 3 still

কখন funcs কার্যকর হবে, এখন স্কোপ চেইন হবে function inner -> function outer। এই সময়টি iবাইরের ফাংশনের স্কোপটিতে পাওয়া যাবে যা লুপের জন্য 3 বার কার্যকর করা হয়, প্রতিটি সময়টির মান iসঠিকভাবে আবদ্ধ হয় । এটি window.iঅভ্যন্তরীণ কার্যকর হলে এর মান ব্যবহার করবে না ।

আরও বিশদ এখানে পাওয়া যাবে
যা আছে তেমনি লুপটিতে ক্লোজার তৈরির সাধারণ ভুল এবং সেইসাথে কেন আমাদের বন্ধকরণ এবং কর্মক্ষমতা বিবেচনার প্রয়োজন তা অন্তর্ভুক্ত।


আমরা খুব কমই এই কোডের নমুনা বাস্তবতে লিখি, তবে আমি মনে করি এটি মৌলিকটি বোঝার জন্য একটি ভাল উদাহরণ দেয়। একবার আমাদের মনে সুযোগ এবং তারা কীভাবে একসাথে বেঁধেছে, এটি কেন আরও 'আধুনিক' উপায় Array.prototype.forEach(function callback(el) {})প্রাকৃতিকভাবে কাজ করে তা আরও স্পষ্টভাবে বোঝা যায় : প্রাকৃতিকভাবে যে কলব্যাকটি পাস হয়েছিল তা প্রতিটি পুনরুক্তিতে সঠিকভাবে আবদ্ধ এল দিয়ে মোড়ানোর সুযোগ তৈরি করে forEach। সুতরাং কলব্যাকে সংজ্ঞায়িত প্রতিটি অভ্যন্তরীণ ফাংশন সঠিক elমানটি ব্যবহার করতে সক্ষম হবে
14 ই 19

13

ES6 ব্লক স্তরের স্কোপিংয়ের নতুন বৈশিষ্ট্যগুলি পরিচালনা করা হয়:

var funcs = [];
for (let i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function() {            // and store them in funcs
        console.log("My value: " + i); // each should log its value.
    };
}
for (let j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

ওপির প্রশ্নের কোডটি letপরিবর্তে পরিবর্তিত হয় var


constএকই ফলাফল সরবরাহ করে এবং যখন ভেরিয়েবলের মান পরিবর্তন হয় না তখন ব্যবহার করা উচিত। তবে constফায়ার লুপের ইনিশিয়ালাইজারের অভ্যন্তরের ব্যবহারটি ফায়ারফক্সে ভুলভাবে প্রয়োগ করা হয়েছে এবং এখনও তা ঠিক করা হয়নি। ব্লকের ভিতরে ঘোষণার পরিবর্তে এটি ব্লকের বাইরে ঘোষণা করা হয়, যার ফলে ভেরিয়েবলের পুনঃনির্মাণ হয়, যার ফলশ্রুতিতে ত্রুটি ঘটে। letইনিশিয়ালাইজারের অভ্যন্তরের ব্যবহার ফায়ারফক্সে সঠিকভাবে প্রয়োগ করা হয়েছে, সুতরাং সেখানে উদ্বিগ্ন হওয়ার দরকার নেই।

10

আমি আশ্চর্য হয়েছি এখনও কেউ forEachস্থানীয় ভেরিয়েবলগুলি ব্যবহার করে ভালভাবে এড়ানো (পুনরায়) ফাংশনটি ব্যবহার করার পরামর্শ দেয়নি । আসলে, আমি for(var i ...)এই কারণে আর ব্যবহার করছি না ।

[0,2,3].forEach(function(i){ console.log('My value:', i); });
// My value: 0
// My value: 2
// My value: 3

// forEachমানচিত্রের পরিবর্তে ব্যবহার করতে সম্পাদিত ।


3
.forEach()যদি আপনি আসলে কোনও ম্যাপিং না করেন তবে এটি একটি আরও ভাল বিকল্প এবং ড্যারিল পরামর্শ দিয়েছিল যে আপনি পোস্ট করার 7 মাস আগে, তাই অবাক হওয়ার মতো কিছুই নেই।
জেএলআরিশ

এই প্রশ্নটি কোনও অ্যারের লুপ সম্পর্কে নয়
ঝেরাক্স

ওয়েল, তিনি ফাংশনগুলির একটি অ্যারে তৈরি করতে চান, এই উদাহরণটি দেখায় যে কোনও বৈশ্বিক চলক জড়িত না করে কীভাবে এটি করা যায়।
ক্রিশ্চিয়ান ল্যান্ডগ্রেন

9

এই প্রশ্নটি সত্যিই জাভাস্ক্রিপ্টের ইতিহাস দেখায়! এখন আমরা তীর ফাংশনগুলির সাথে ব্লক স্কোপিং এড়াতে পারি এবং অবজেক্ট পদ্ধতিগুলি ব্যবহার করে সরাসরি ডোম নোডগুলি থেকে লুপগুলি পরিচালনা করতে পারি।

const funcs = [1, 2, 3].map(i => () => console.log(i));
funcs.map(fn => fn())

const buttons = document.getElementsByTagName("button");
Object
  .keys(buttons)
  .map(i => buttons[i].addEventListener('click', () => console.log(i)));
<button>0</button><br>
<button>1</button><br>
<button>2</button>


8

আপনার আসল উদাহরণটি কাজ না করার কারণটি হ'ল লুপে আপনি তৈরি সমস্ত বন্ধন একই ফ্রেমের রেফারেন্স করেছে। বাস্তবে, কেবল একটি একক iভেরিয়েবলের সাথে একটি অবজেক্টে 3 টি পদ্ধতি রয়েছে । তারা সবাই একই মান ছাপিয়েছে।


8

প্রথমত, এই কোডটিতে কী কী আছে তা বুঝতে পারেন:

var funcs = [];
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function() {            // and store them in funcs
        console.log("My value: " + i); // each should log its value.
    };
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

এখানে যখন funcs[]অ্যারেটি শুরু করা হচ্ছে, বাড়ানো iহচ্ছে, funcsঅ্যারেটি আরম্ভ করা হবে এবং funcঅ্যারের আকার 3 হবে, তাই i = 3,। এখন যখন funcs[j]()ডাকা হবে তখন এটি আবার চলকটি ব্যবহার করছে iযা ইতিমধ্যে 3 এ বাড়ানো হয়েছে।

এখন এটি সমাধান করতে আমাদের কাছে অনেকগুলি বিকল্প রয়েছে। নীচে তাদের দুটি:

  1. আমরা আরম্ভ করতে পারেন iসঙ্গে letঅথবা একটি নতুন পরিবর্তনশীল আরম্ভ indexসঙ্গে letএবং এটি সমান করা i। সুতরাং যখন কল করা হচ্ছে, indexব্যবহৃত হবে এবং এর সুযোগ শুরু হওয়ার পরে শেষ হবে। এবং কল করার জন্য, indexআবার শুরু করা হবে:

    var funcs = [];
    for (var i = 0; i < 3; i++) {          
        let index = i;
        funcs[i] = function() {            
            console.log("My value: " + index); 
        };
    }
    for (var j = 0; j < 3; j++) {
        funcs[j]();                        
    }
  2. অন্যান্য অপশনটি এমন একটি উপস্থাপন করা যেতে পারে tempFuncযা আসল ফাংশনটি দেয়:

    var funcs = [];
    function tempFunc(i){
        return function(){
            console.log("My value: " + i);
        };
    }
    for (var i = 0; i < 3; i++) {  
        funcs[i] = tempFunc(i);                                     
    }
    for (var j = 0; j < 3; j++) {
        funcs[j]();                        
    }

8

ক্লোজার স্ট্রাকচার ব্যবহার করুন , এটি লুপের জন্য আপনার অতিরিক্ত হ্রাস করবে। লুপের জন্য আপনি এটি এককভাবে করতে পারেন:

var funcs = [];
for (var i = 0; i < 3; i++) {     
  (funcs[i] = function() {         
    console.log("My value: " + i); 
  })(i);
}

7

আমরা যাচাই করবো, যখন আপনি ঘোষণা করেন varএবং let একের পর এক প্রকৃতপক্ষে কী ঘটে ।

কেস 1 : ব্যবহার করেvar

<script>
   var funcs = [];
   for (var i = 0; i < 3; i++) {
     funcs[i] = function () {
        debugger;
        console.log("My value: " + i);
     };
   }
   console.log(funcs);
</script>

এখন আপনার ক্রোম কনসোল উইন্ডোটি এফ 12 টিপে টিপুন এবং পৃষ্ঠাটি রিফ্রেশ করুন। অ্যারের অভ্যন্তরে প্রতি 3 টি কার্য ব্যয় করুন You আপনি একটি সম্পত্তি [[Scopes]]দেখবেন that আপনি একটি অ্যারে অবজেক্ট দেখতে পাবেন "Global", এটি প্রসারিত করুন। আপনি 'i'অবজেক্টে ঘোষিত একটি সম্পত্তি পাবেন যার মান 3 রয়েছে।

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

উপসংহার:

  1. আপনি যখন 'var'কোনও ফাংশনের বাইরে ব্যবহার করে কোনও ভেরিয়েবল ঘোষণা করেন , এটি বৈশ্বিক পরিবর্তনশীল হয়ে যায় (আপনি টাইপ করে iবা window.iকনসোল উইন্ডোতে পরীক্ষা করতে পারেন t এটি ফিরে আসবে 3)।
  2. আপনি ঘোষিত কুখ্যাত ফাংশনটি ফাংশনটির জন্য অনুরোধ না করা হলে ফাংশনের অভ্যন্তরের মানটি কল করবে না এবং চেক করবে না।
  3. আপনি যখন ফাংশনটি চালু করেন, তখন console.log("My value: " + i)তার Globalবস্তু থেকে মানটি নিয়ে ফলাফলটি প্রদর্শিত হয়।

CASE2: লেট ব্যবহার করে

এখন 'var'সঙ্গে প্রতিস্থাপন'let'

<script>
    var funcs = [];
    for (let i = 0; i < 3; i++) {
        funcs[i] = function () {
           debugger;
           console.log("My value: " + i);
        };
    }
    console.log(funcs);
</script>

একই জিনিস করুন, স্কোপগুলিতে যান। এখন আপনি দুটি বস্তু দেখতে পাবেন "Block"এবং "Global"। এখন Blockঅবজেক্ট অবজেক্ট করুন, আপনি দেখতে পাবেন যে সেখানে 'i' সংজ্ঞায়িত হয়েছে, এবং আশ্চর্যের বিষয়টি হ'ল প্রতিটি ফাংশনের জন্য মানটি যদি iআলাদা হয় (0, 1, 2)।

এখানে চিত্র বর্ণনা লিখুন

উপসংহার:

আপনি যখন 'let'ফাংশনটির বাইরেও লুপের অভ্যন্তরে ভেরিয়েবল ঘোষণা করেন তবে এই ভেরিয়েবলটি গ্লোবাল ভেরিয়েবল হবে না, এটি একটি Blockস্তর ভেরিয়েবল হয়ে উঠবে যা কেবল একই ফাংশনের জন্য উপলব্ধ। এটি কারণ, আমরা এর মান পাচ্ছিi বিভিন্ন প্রতিটি ফাংশনের জন্য যখন আমরা ফাংশনগুলি প্রার্থনা করি।

কীভাবে কাছাকাছি কাজ করে সে সম্পর্কে আরও তথ্যের জন্য, দয়া করে দুর্দান্ত ভিডিও টিউটোরিয়াল https://youtu.be/71AtaJpJHw0 দেখুন


4

আপনি কোয়েরি-জেএস (*) এর মতো ডেটার তালিকার জন্য একটি ঘোষিত মডিউল ব্যবহার করতে পারেন । এই পরিস্থিতিতে আমি ব্যক্তিগতভাবে একটি ঘোষণামূলক পদ্ধতির কম অবাক লাগে

var funcs = Query.range(0,3).each(function(i){
     return  function() {
        console.log("My value: " + i);
    };
});

তারপরে আপনি আপনার দ্বিতীয় লুপটি ব্যবহার করতে পারেন এবং প্রত্যাশিত ফলাফলটি পেতে পারেন বা আপনি করতে পারেন

funcs.iterate(function(f){ f(); });

(*) আমি ক্যোয়ারী-জেএসের লেখক এবং এর জন্য এটি ব্যবহারের পক্ষপাতদুষ্ট, সুতরাং আমার বক্তব্যকে কেবলমাত্র ঘোষণামূলক পদ্ধতির জন্য উক্ত গ্রন্থাগারের সুপারিশ হিসাবে গ্রহণ করবেন না :)


1
আমি নীচের ভোটের একটি ব্যাখ্যা পছন্দ করব। কোডটি সমস্যাটি সমাধান করে। কীভাবে কোডটি সম্ভাব্যভাবে উন্নত করা যায় তা জানার জন্য মূল্যবান হবে
রুন এফএস

1
কী Query.range(0,3)? এটি এই প্রশ্নের ট্যাগগুলির অংশ নয়। এছাড়াও, আপনি যদি কোনও তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করেন তবে আপনি ডকুমেন্টেশনের লিঙ্কটি সরবরাহ করতে পারেন।
ঝেরাক্স

1
@ ঝেরাক্স সেগুলি বা অবশ্যই স্পষ্টত উন্নতি হয়েছে। মন্তব্যের জন্য ধন্যবাদ. আমি শপথ করতে পারি যে ইতিমধ্যে একটি লিঙ্ক ছিল। পোস্টটি বেশ অর্থহীন ছিল বলে আমি অনুমান করি :)। এটি চালিয়ে যাওয়ার আমার প্রাথমিক ধারণাটি হ'ল কারণ আমি নিজের লাইব্রেরিটি ব্যবহার করার চেষ্টা করছি না বরং আরও ঘোষণামূলক ধারণা। তবে অন্তর্দৃষ্টিতে আমি পুরোপুরি সম্মত হই যে লিঙ্কটি সেখানেই থাকতে হবে
Rune FS

4

আমি forEachফাংশনটি ব্যবহার করতে পছন্দ করি , যার ছদ্ম পরিসীমা তৈরির সাথে নিজস্ব বন্ধ রয়েছে:

var funcs = [];

new Array(3).fill(0).forEach(function (_, i) { // creating a range
    funcs[i] = function() {            
        // now i is safely incapsulated 
        console.log("My value: " + i);
    };
});

for (var j = 0; j < 3; j++) {
    funcs[j](); // 0, 1, 2
}

এটিকে অন্যান্য ভাষার ব্যাপ্তির চেয়ে দেখতে দেখতে খারাপ লাগে তবে আইএমএইচও অন্যান্য সমাধানগুলির চেয়ে কম ভয়ানক।


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

এটি উল্লিখিত ইস্যুটির সাথে ঠিক সম্পর্কিত: ক্লোজার সমস্যা ছাড়াই কীভাবে নিরাপদে পুনরাবৃত্তি করা যায়
র্যাক্স ওয়ান্টার

এখন এটি গৃহীত উত্তরের চেয়ে উল্লেখযোগ্যভাবে আলাদা বলে মনে হচ্ছে না।
কোয়ান্টিন

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

@ কুইন্টিন আমি কমিয়ে দেওয়ার আগে সমাধানটি তদন্ত করার পরামর্শ দেব
রাক্স ওয়ান্টার

4

এবং এখনও অন্য সমাধান: অন্য লুপ তৈরির পরিবর্তে, কেবলমাত্র thisরিটার্ন ফাংশনে আবদ্ধ করুন ।

var funcs = [];

function createFunc(i) {
  return function() {
    console.log('My value: ' + i); //log value of i.
  }.call(this);
}

for (var i = 1; i <= 5; i++) {  //5 functions
  funcs[i] = createFunc(i);     // call createFunc() i=5 times
}

দ্বারা বাঁধাই এই , সমস্যা হিসাবে ভাল solves।


3

অনেকগুলি সমাধান সঠিক বলে মনে হয় তবে তারা এটিকে বলা হয় না Curryingযা এখানকার পরিস্থিতির জন্য একটি কার্যকরী প্রোগ্রামিং ডিজাইনের ধরণ। ব্রাউজারের উপর নির্ভর করে বাইন্ডের চেয়ে 3-10 গুণ বেশি দ্রুত।

var funcs = [];
for (var i = 0; i < 3; i++) {      // let's create 3 functions
  funcs[i] = curryShowValue(i);
}
for (var j = 0; j < 3; j++) {
  funcs[j]();                      // and now let's run each one to see
}

function curryShowValue(i) {
  return function showValue() {
    console.log("My value: " + i);
  }
}

বিভিন্ন ব্রাউজারে পারফরম্যান্স লাভ দেখুন ।


@ টিনিজিয়ান্ট ফাংশনটি দিয়ে ফিরে আসার উদাহরণটি এখনও পারফরম্যান্সের জন্য অনুকূল হয়ে উঠছে। আমি সমস্ত জাভাস্ক্রিপ্ট ব্লগারগুলির মতো তীর ফাংশন ব্যান্ডওয়াগনে ঝাঁপ দেব না। এগুলি দেখতে দুর্দান্ত এবং পরিষ্কার তবে পূর্বনির্ধারিত ফাংশনগুলি ব্যবহার না করে লেখার ফাংশনগুলিকে ইনলাইন প্রচার করে। এটি গরম জায়গায় কোনও অ-স্পষ্ট ফাঁদ হতে পারে। আরেকটি সমস্যা হ'ল এগুলি কেবল সিনট্যাকটিক চিনি নয় কারণ তারা অযৌক্তিকভাবে বাঁধাই চালাচ্ছে যার ফলে মোড়ক বন্ধ হয়ে যায়।
পাভেল

2
ভবিষ্যতের পাঠকদের জন্য সতর্কতা: এই উত্তরটি সঠিকভাবে কারিইং শব্দটি প্রয়োগ করে । "তরকারীকরণ তখনই হয় যখন আপনি কোনও ফাংশন ভাঙেন যা একাধিক যুক্তিগুলিকে ক্রিয়াকলাপে যুক্ত করে যা আর্গুমেন্টের অংশ নেয়" " । এই কোডটি বাছাই করে কিছুই করে না। আপনি এখানে যা কিছু করেছেন তা হ'ল গৃহীত উত্তর থেকে কোড নেওয়া, কিছু জিনিস ঘুরিয়ে দেওয়া, স্টাইল পরিবর্তন করা এবং কিছুটা নামকরণ করা, তারপরে এটিকে তরকারী বলা, যা এটি স্পষ্টতই নয়।

3

আপনার কোড কাজ করে না, কারণ এটি যা করে তা হ'ল:

Create variable `funcs` and assign it an empty array;  
Loop from 0 up until it is less than 3 and assign it to variable `i`;
    Push to variable `funcs` next function:  
        // Only push (save), but don't execute
        **Write to console current value of variable `i`;**

// First loop has ended, i = 3;

Loop from 0 up until it is less than 3 and assign it to variable `j`;
    Call `j`-th function from variable `funcs`:  
        **Write to console current value of variable `i`;**  
        // Ask yourself NOW! What is the value of i?

এখন প্রশ্নটি হল, iফাংশনটি যখন বলা হয় তখন ভেরিয়েবলের মান কত ? যেহেতু প্রথম লুপটি কন্ডিশনের সাথে তৈরি হয়েছিল i < 3, এটি শর্তটি মিথ্যা হলে অবিলম্বে বন্ধ হয়ে যায়, তাই এটি i = 3

আপনার বুঝতে হবে যে সময়ে যখন আপনার ফাংশনগুলি তৈরি করা হয়, তখন তাদের কোডগুলির কোনওটিই কার্যকর হয় না, এটি কেবল পরে সংরক্ষণ করা হয়। এবং সুতরাং যখন তাদের পরে বলা হয়, দোভাষী তাদের সম্পাদন করে এবং জিজ্ঞাসা করেন: "বর্তমানের মূল্য কী i?"

সুতরাং, আপনার লক্ষ্যটি হ'ল প্রথমে iফাংশনটির মান সংরক্ষণ করুন এবং তারপরেই ফাংশনটি সেভ করুন funcs। এটি উদাহরণস্বরূপ এইভাবে করা যেতে পারে:

var funcs = [];
for (var i = 0; i < 3; i++) {          // let's create 3 functions
    funcs[i] = function(x) {            // and store them in funcs
        console.log("My value: " + x); // each should log its value.
    }.bind(null, i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}

এই ভাবে, প্রতিটি ফাংশন এটা নিজস্ব পরিবর্তনশীল থাকবে xএবং আমরা এই সেট xএর মান iপ্রতিটি পুনরাবৃত্তির।

এই সমস্যাটি সমাধানের একাধিক উপায় এটি।


3
var funcs = [];
for (var i = 0; i < 3; i++) {      // let's create 3 functions
  funcs[i] = function(param) {          // and store them in funcs
    console.log("My value: " + param); // each should log its value.
  };
}
for (var j = 0; j < 3; j++) {
  funcs[j](j);                      // and now let's run each one to see with j
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.