DEV Community

Mehedi Hasan Joy
Mehedi Hasan Joy

Posted on • Edited on

Closure in Javascript(Bangla) With Joy

ক্লোজার কি? জাভাস্ক্রিপ্টের কিছু অদ্ভুত আচরণের মধ্যে অসাধারণ একটা কনসেপ্ট হলো ক্লোজার,

এ কেমন কথা, অদ্ভুত আবার অসাধারণ হয় কিভাবে ?

চলুন আজকে একটু ক্লোজার নিয়ে গল্প করি, প্রথমে আসি অদ্ভুত আচরণ নিয়ে,জাভাস্ক্রিপ্টে লোকালি ডিক্লেয়ার করা কোন ভেরিয়েবল ততক্ষণ সক্রিয় থাকে যতক্ষণ এটি তার প্যারেন্ট এক্সিকিউশন কন্টেক্সটের অংশ হিসেবে রেফারেন্স করা হয় বা প্রয়োজন হয়। কনসেপ্টটি মাথার উপর দিয়ে গেল? চলুন আমরা আগে একটা কাউন্টার ফাংশন তৈরি করার চেষ্টা করি।
‌‌‌‌

  function sum(){
    let a=10;
    let b=20
    return a+b
 }
 console.log(sum()) //30
Enter fullscreen mode Exit fullscreen mode

উপরক্ত ফাংশনের ডিক্লেয়ার করা ‌‌a‌ এবং b ফাংশন এক্সিকিউশন কন্টেক্সটে এলাইভ ছিল। যখনি ফাংশনের কার্যসম্পাদন শেষ তখনি জাভাস্ক্রিপ্ট ভেরিয়েবল দুটোকে গার্বেজ কালেক্টর দ্বারা অপসারিত করা হয়। চলুন এরকম আরেক ভিন্ন ধর্মি কার্যক্রম দেখি:-

 function sum(){
    let a=10;
    let b=20;
    let c=12;
    return a+b;
}
console.dir(sum()) 

Enter fullscreen mode Exit fullscreen mode

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

সবই তো বুঝলাম তাহলে ক্লোজার কি? এটা কখন ব্যবহার করব?

চলুন ক্লোজারকে ওপেন হার্ট সার্জারি করি। যেহেতু প্রোগ্রামেটিক তথ্য গুলো গানিতিক ভাবে ভালো বোঝানো যায় তাই চলুন একটু গানিতিক ভাবে এর মূল উৎপাটন করি।

মনে করুন আপনি একটি কাউন্টার তৈরি করবেন যেটা প্রতিবার ক্লিক করার মাধ্যমে এর ভ্যালু পরিবর্তন হবে। কথা শুনে মনে হতে পারে এ এমন কি কাজ ? এটাতো খুবই সহজ! হ্যা ক্লোজার ও খুবই সহজ শুধু কনসেপ্টা নিয়েই একটু কনফিউশন।

let a=10;

function sum(){
return a=a+1
}
console.log(sum()) // 11
console.log(sum()) // 12
console.log(sum()) // 13


Enter fullscreen mode Exit fullscreen mode

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

let a=10;

function sum(){
return a=a+1
}
console.log(sum()) // 11
console.log(sum()) // 12
console.log(sum()) // 13
 a++
 a++
 a++
 console.log(a) // 16
Enter fullscreen mode Exit fullscreen mode

এখানে ম্যানুয়ালি a এর মান পরিবর্তন করা হয়েছে চাইলে আরো কয়েকভাবে এটা করা যেত। কিন্তু আপনি চাচ্ছেন কাউন্টার কেবল আপনার নির্দেশে নির্দিষ্ট কোন ফাংশনের ফাংশনালিটির উপর ভিত্তি করে a এর ভ্যালু পরিবর্তন করবেন।
মানে a এর অ্যাক্সেস শুধু আপনার কাছেই থাকবে। এমতাবস্থায় আপনার মনে হতে পারে let a =10 এটাকে ফাংশন স্কোপের মধ্যে নিলেই তো হয়। চলুন দেখি কি হয়।

function sum(){
    let a=10;
return a=a+1
}
console.log(sum()) // 11
console.log(sum()) // 11
console.log(sum()) // 11

Enter fullscreen mode Exit fullscreen mode

যা ! একি হলো? কেন কাজ করতেছে না? এতশত প্রশ্নের সিম্পল উত্তর হলো ফাংশন এক্সিকিউশন পলিসি। এটা আবার কি? sum ফাংশন যখন কল করা হয় তখন প্রথমেই দেখে let a =10 সুতরাং সে a এর ভ্যালু ১০ সেট করে এবং পরে যখন a=a+1 লজিক পায়, তখন লজিক অনুযায়ি a এর ভ্যালু বাড়ায় এবং ১১ রিটার্ন করে। এই কাজটাই ফাংশন রিপিটেডলি করতে থাকে। মনে হতে পারে কেন a এর ভ্যালু জাভাস্ক্রিপ্ট মনে রাখেনা? এবিষয় আমরা প্রথমেই আলোচনা করেছি

যখনি ফাংশনের কার্যসম্পাদন শেষ তখনি জাভাস্ক্রিপ্ট ভেরিয়েবল গুলো গার্বেজ কালেক্টর দ্বারা অপসারিত করা হয়। যেকারনে পুন:রায় ভ্যারিয়েবল নতুন করে এক্সিউট হয়।

এরকম কোন সিস্টেম হলো কেমন হতো, যদি ফাংশনকে একবার কল করব কিন্তু লজিকটা বার বার ব্যবহার করব। বিষয়টা তাহলে মজার হতো না?

এখন তাহলে উপায়?
এই মহা সমস্যার উপায় নিয়েই হাজির ক্লোজার। প্রথমে নিচের কোড ফলো করুন।

function sum(){
    let a=10;
    function logic(){
        return a=a+1
    }
    return logic
}
const logic=sum()
console.log(logic()) // 11
console.log(logic()) // 12
Enter fullscreen mode Exit fullscreen mode

আরে বাহ! কোড কাজ করতেছে। কিন্তু কনফিউশন তো দুর হলো না, কিভাবে কাজ করলো? ক্লোজার কোথায়? কোডে মুলত sum ফাংশনকে কল করে logic নামক ভ্যারিয়েবলে স্টোর হচ্ছে । sum ফাংশনকে কল করলে মুলত sum এর মধ্যে থাকা logic ফাংশনই রিটার্ন করে।
এখন চলুন একটা একটা করে প্রশ্নের উত্তর দেই। কিভাবে কাজ করল?
ক্লোজার ফাংশনটির মধ্যে থাকা লোকাল ভেরিয়েবলগুলি "লক" করা হয় এবং এক্সিকিউশন কন্টেক্সট শেষ হওয়ার পরেও সেই ভেরিয়েবলগুলিকে রেফারেন্স করা যায়। এটিই ক্লোজারের মূল কাজ।
জাভাস্ক্রিপ্টে, আমি স্কোপের যেখানে অবস্থান করছি তার উপরের সকল স্কোপের অ্যাক্সেস থাকে (স্কোপ কি? এবিষয় না হয় আরেকদিন আলোচনা করব) উপরের কোডে logic ফাংশন let a =10 এর অ্যাক্সেস পাচ্ছে। যেহেতু এটা তার উপরের লোকাল স্কোপে অবস্থান করতেছে।তাই logic ফাংশন a এর ভ্যালু পরিবর্তন করতে পারতেছে। এখন আবার আপনার মাথায় প্রশ্ন আসতে পারে (যেহেতু আপনি ব্রিলিয়েন্ড জাভাস্ক্রিপ্ট লার্নার) যে একটু আগে বললেন ফাংশনের এক্সিকিউশন শেষ হয়ে গেলে ভেরিয়েবল গুলো destroy হয়ে যায়, তাহলে কিভাবে a এর ভ্যালু অপরিবর্তিত থাকছে? এখানেই মুলত ক্লোজার কাজ করছে যা দেখতে হলে আপনাকে console.dir(logic) করতে হবে।

Image description
Scopes এর ভিতরে আমরা দেখতে পাচ্ছি closure নামক এক ভদ্রলোক sum নামক ফাংশনকে রেফার করে a এর বর্তমান ভ্যালু দেখাচ্ছে। এতো আলোচনা যাকে নিয়ে সে কিনা এখানে এসে বসে আছে।বুঝলাম! তো এখানে বসে আসলে কি করছে?
সে তেমন কিছুই করতেছেনা শুধু let a ভ্যারিয়েবলের সাথে সুসম্পর্ক বজায় রেখে তার সাথে গানিতিক হিসাব করতেছে। ক্লোজার মুলত let a ভেরিয়েবলকে রেফারেন্স করে রাখছে যাতে গার্বেজ কালেক্টর এটাকে destroy না করে।যেহেতু let a কে নিয়েই logic function কাজ করতেছে তাই ক্লোজার let a কে রেফারেন্স হিসেবে রেখে প্রতিবার let a এর ভ্যালু আপডেট করতেছে। এই সিম্পল কাজটাই ক্লোজার।রেফারেন্স করে ভেরিয়বলকে এলাইভ রাখছে।
আর যেহেতু a কে ফাংশনের মধ্যে ডিকলার করা হয়েছে, তাই চাইলেও তাকে বাইরে থেকে মডিফাই করা যাবে না এবং লজিক অনুযায়ি আমাদের কাউন্টারও তৈরি করা হলো।মেইন ফাংশন বার বার কল না করেও অন্তবর্তি ভ্যারিয়েবলের ভ্যালু পরিবর্তন করতে পারলাম। আমাদের সকল সমস্যা সমাধান করলো Closure

আমাদের আজকের আড্ডাটা এখানেই রাখলাম।অন্যদিন অন্য কোন টপিক নিয়ে আবার আড্ডা দিব।

Top comments (0)