2.8 জাভাস্ক্রিপ্টে ক্লোজার
Closure কোন ফাংশন না আবার ফাংশনও কোন closure না। Closure হচ্ছে ফাংশনের এমন একটা বৈশিষ্ট্য যে বৈশিষ্ট্যের কারণে ফাংশন এক্সিকিউশন শেষ হয়ে যাবার পরেও তার lexical scope এ অবস্থিত সকল variable কে মনে রাখতে পারে। উদাহরণস্বরূপ বলা যেতে পারে যে ডম থেকে কিছু অ্যাক্সেস করার জন্যে আমরা যে ইভেন্ট ফাইয়ার করি সেটাও একটা closure।
কিছু উদাহরণঃ
কি হচ্ছে এসব?? ঠিক আছে, চলেন দেখি কোডগুলোকে ভেঙ্গেঃ-
১। যখন add ফাংশনটি কল হয় এটি আরেকটি ফাংশনকে return করে।
২। ঐ ফাংশনটির এক্সিকিউশন শেষ হয়ে যায় এবং মনে রাখে ঐ সময় তার প্যারামিটার a এর ভ্যালু কি ছিল।
৩। যখন addTen ভেরিয়েবলে add ফাংশনকে এসাইন করা হয়। এটি সব সময় মনে রাখবে a এর ভ্যালু কি ছিল যখন এটিকে ইনিশিয়ালি কল করা হয়েছিল।
৪। উপরের addTen ভেরিয়েবল একটি ফাংশনকে বোঝায় যেটি সব সময় ভ্যালু ১০ যোগ করবে যা পাঠানো হয়েছিল।
৫। তার মানে হল যখন addTen কে কল করা হয় ৭ ভ্যালু দিয়ে, এটি ১০ এর সাথে ৭ যোগ করবে এবং ১৭ রিটার্ন করবে।
সুতরাং, জাভাস্ক্রিপ্ট ইঞ্জিন addTen কে যেভাবে রান করেঃ-
এখন একটা মজার উদাহরণ দেখবো। কিভাবে আমরা লুপের ভিতরে ক্লোজার চালাতে পারি। এটি ইন্টার্ভিউ বোর্ডের একটা কমন প্রশ্ন। নিচের কোডটা দেখেন এবং একটু মনে মনে চিন্তা করেন এটার আউটপুট কত হবে।
আসলে এই আউটপুট আসার অনেক কারণ আছে। লুপের মাঝে ভ্যারিয়েবল i হচ্ছে একটি গ্লোবাল ভ্যারিয়েবল। যখন setTimeout রান হয় তার আগেই লুপ শেষ হয়ে যায় এবং তাই i ভ্যালু 6 হয়ে যায়। সেজন্যে প্রতি এক সেকন্ড পর পর পাঁচবার 6 দেখাচ্ছে। যদি বিশ্বাস না হয় তাহলে কোডটা রান করার পর আপনার গ্লোবাল window অবজেক্টটা একবার দেখেন সেখানে i নামে একটা ভ্যারিয়েবল দেখতে পারবেন এবং তার ভ্যালু 6 হয়ে আছে।
এই সমস্যার সমাধান আমরা IIFE বা Immediately Invoked Function Expression ব্যবহার করে করতে পারি। নিচে উদাহরণ দেওয়া হলঃ-
পদ্ধতি ১ঃ
পদ্ধতি ২ঃ
এখানে আমরা একটা ফাংশন লিখে একটা Scope তৈরি করেছি। ফাংশনটিকে ইমিডিয়েটলি কল করেছি এবং তার প্যারামিটারের ভ্যালু হিসাবে i কে পাস করেছি। এতে সে এখন i এর ভ্যালুকে মনে না রেখে সে এখন তার প্যারামিটারের ভ্যালুকে মনে রাখবে। মানে এখন i এর মান 1, 2 করে যাচ্ছে এবং সেটা থেকে একটা আলাদা Scope তৈরি হচ্ছে যেটাকে সে মনে রাখছে।
পদ্ধতি ৩ঃ
অবশেষে আমাদের কাঙ্ক্ষিত আউটপুট পেলাম। তবে আজ এই পর্যন্তই কথা হবে পরবর্তীতে অন্য কোনো টপিক নিয়ে।
-
for (var count = 1; count <= 5; count++) {setTimeout(() => console.log(count), 1000);}// Output:// 6// 6// 6// 6// 6
-
সেল্ফ ইনভোকিং ফাংশনে ক্লোজারconst add = (function () {let counter = 0;return function () {counter += 1;return counter;};})();add();add();add();
- Every closure has three scopes:
Local Scope (Own scope)
Outer Functions Scope
Global ScopeHere’s a series of nested functions, all of which have access to the outer functions’ scope. In this context, we can say that closures have access to all outer function scopes.
// global scopevar e = 10;function sum(a) {return function (b) {return function (c) {// outer functions scopereturn function (d) {// local scopereturn a + b + c + d + e;};};};}console.log(sum(1)(2)(3)(4)); // log 20
- জাভাস্ক্রিপ্টে ক্লোজার কি?
- জাভাস্ক্রিপ্টে ক্লোজার সুবিধা কি?
-
নিচের কোডের আউটপুট কি হবে?const multiply = (x) => {return function (y) {return x * y;};};let multiply10 = multiply(10);let multiplyFive = multiply10(5);console.log(multiplyFive);
- নিচের কোডের আউটপুট কি হবে?
for (var count = 1; count <= 5; count++) {setTimeout(() => console.log(count), 1000);}