টাইপস্ক্রিপ্টে ক্লোজার
এই প্রবন্ধে, আমরা টাইপস্ক্রিপ্টে ক্লোজার ব্যাখ্যা করব।
YouTube Video
টাইপস্ক্রিপ্টে ক্লোজার
ক্লোজার কী?
ক্লোজার বলতে একটি ফাংশন যেখানে সংজ্ঞায়িত হয়েছে, সেই স্কোপে (পরিবেশে) রেফারেন্স ধরে রাখার ক্ষমতাকে বোঝায়, এমনকি যদি ফাংশনটি সেই স্কোপের বাইরে থেকে কল করা হয় তবুও। নিচে টাইপ অ্যানোটেশনসহ ক্লোজার ব্যাখ্যা করা হয়েছে।
সহজভাবে বললে, একটি ক্লোজার হচ্ছে একটি ফাংশন এবং যেখানে ফাংশনটি সংজ্ঞায়িত হয়েছিল সেই পরিবর্তনশীল পরিবেশের সংমিশ্রণ, যা ফাংশন কল করা হলে ঐ পরিবেশে অ্যাক্সেসের সুযোগ দেয়।
ক্লোজারের মৌলিক কার্যপ্রণালী
টাইপস্ক্রিপ্টে, যখন একটি ফাংশনের ভেতরে আরেকটি ফাংশন সংজ্ঞায়িত করা হয়, তখন ভেতরের ফাংশনটি বাইরের ফাংশনের পরিবর্তনশীলগুলো অ্যাক্সেস করতে পারে তা স্পষ্ট হয়। এখানে টাইপ অ্যানোটেশন সহ ক্লোজারের একটি মৌলিক উদাহরণ রয়েছে।
1function outerFunction(): () => void {
2 let outerVariable: string = "I am from outer function";
3
4 function innerFunction(): void {
5 // The inner function accesses the variable of the outer function
6 console.log(outerVariable);
7 }
8
9 return innerFunction;
10}
11
12const closure: () => void = outerFunction();
13closure(); // "I am from outer function"
outerFunction
-এর রিটার্ন টাইপ হলো() => void
, যা নির্দেশ করে এটি একটি ফাংশন রিটার্ন করে।innerFunction
-এর টাইপ স্পষ্টভাবেvoid
নির্ধারিত হয়েছে, অর্থাৎ এর কোনো রিটার্ন ভ্যালু নেই।
ক্লোজারের ব্যবহার ও সুবিধা
ডাটা এনক্যাপসুলেশন
নিচে ডাটা এনক্যাপসুলেশনের জন্য টাইপ অ্যানোটেশন সহ ক্লোজারের একটি উদাহরণ দেওয়া হয়েছে।
1function createCounter(): () => number {
2 let count: number = 0;
3
4 return function (): number {
5 count += 1;
6 return count;
7 };
8}
9
10const counter: () => number = createCounter();
11console.log(counter()); // 1
12console.log(counter()); // 2
13console.log(counter()); // 3
createCounter
ফাংশনটি() => number
টাইপের একটি ফাংশন রিটার্ন করে।count
পরিবর্তনশীলটিnumber
টাইপ হিসেবে সংজ্ঞায়িত এবং ক্লোজারের ভেতরে এটি ব্যবহৃত হয়।
হায়ার-অর্ডার ফাংশন
হায়ার-অর্ডার ফাংশন তৈরি করার সময় ক্লোজার অত্যন্ত উপযোগী। নিচে পরিষ্কার টাইপ অ্যানোটেশন সহ হায়ার-অর্ডার ফাংশনের একটি উদাহরণ রয়েছে।
1function createMultiplier(multiplier: number): (value: number) => number {
2 return function (value: number): number {
3 return value * multiplier;
4 };
5}
6
7const double: (value: number) => number = createMultiplier(2);
8console.log(double(5)); // 10
9
10const triple: (value: number) => number = createMultiplier(3);
11console.log(triple(5)); // 15
createMultiplier
একটিnumber
টাইপের আর্গুমেন্ট নেয় এবং(value: number) => number
টাইপের একটি ফাংশন রিটার্ন করে।- ভেতরের ফাংশনটিও
value
কেnumber
টাইপ হিসেবে গ্রহণ করে এবং ফলাফলnumber
টাইপে রিটার্ন করে।
টাইপস্ক্রিপ্টে ক্লোজার প্রয়োগের উদাহরণ
টাইপ অ্যানোটেশন সহ একটি রেঞ্জ-বাউন্ড কাউন্টার ক্লোজার আকারে বাস্তবায়ন করুন।
1function rangeCounter(min: number, max: number): () => number | string {
2 let count: number = min;
3
4 return function (): number | string {
5 if (count <= max) {
6 return count++;
7 } else {
8 return `Count has exceeded the maximum value: ${max}`;
9 }
10 };
11}
12
13const counter: () => number | string = rangeCounter(1, 5);
14
15console.log(counter()); // 1
16console.log(counter()); // 2
17console.log(counter()); // 3
18console.log(counter()); // 4
19console.log(counter()); // 5
20console.log(counter()); // "Count has exceeded the maximum value: 5"
rangeCounter
ফাংশনটি এমন একটি ফাংশন রিটার্ন করে যা হয়number
অথবাstring
রিটার্ন করতে পারে।- ভেতরের ফাংশনে, যদি
count
max
-কে অতিক্রম করে, তবে এটিstring
টাইপের মেসেজ রিটার্ন করে; নতুবা, এটিnumber
টাইপ রিটার্ন করে।
ক্লোজার ব্যবহারের সতর্কতা
ক্লোজার থেকে সম্ভাব্য মেমরি লিক
ক্লোজার বাইরের স্কোপের পরিবর্তনশীল ধরে রাখতে পারে, যা কখনও কখনও মেমরি লিকের কারণ হতে পারে। অপ্রয়োজনীয় ক্লোজারগুলোকে স্পষ্টভাবে মেমরি থেকে মুক্ত করতে হবে।
1function createLeak(): () => void {
2 // Large array consuming significant memory
3 const largeArray: string[] = new Array(1000000).fill("leak");
4
5 // Closure capturing `largeArray`
6 return function (): void {
7 console.log(largeArray[0]); // Using the captured array
8 };
9}
10
11// Create a closure that holds a reference to the large array
12let leakyFunction = createLeak();
13
14// The large array is not released as `leakyFunction` still references it
15
16// When the object is no longer needed
17leakyFunction = null; // Explicitly remove the reference
- এই কোডে
createLeak
-এর ভিতরে তৈরি হওয়াlargeArray
-কে স্কোপের বাইরে চলে গেলে রিলিজ হয়ে যাওয়ার কথা, কিন্তু ক্লোজারটিlargeArray
-কে ধরে রাখার কারণে তা হয় না।leakyFunction
যতক্ষণ বিদ্যমান থাকে, এই অপ্রয়োজনীয় মেমরি বজায় থাকবে। - কোনও অবজেক্ট বা পরিবর্তনশীলের আর প্রয়োজন না হলে, তার রেফারেন্স
null
করে দিলে গার্বেজ কালেক্টর তা সনাক্ত করে মেমরি মুক্ত করতে পারে।
লুপে ক্লোজারের অপব্যবহার
লুপের ভিতরে ক্লোজার তৈরি করলে একই পরিবর্তনশীলের প্রতি রেফারেন্স নিয়ে সমস্যা হতে পারে। নিম্নলিখিত উদাহরণে দেখানো হয়েছে, যেখানে i
পরিবর্তনশীলটি সঠিকভাবে কাজ করে না।
1for (var i: number = 0; i < 3; i++) {
2 setTimeout((): void => {
3 console.log(i);
4 }, 1000);
5}
6// Output: 3, 3, 3
এই কোড কাঙ্ক্ষিত ফলাফল দেয় না কারণ লুপের শেষে i
পরিবর্তনশীলের মান ৩ থাকে। এটি ঠিক করতে, স্কোপ আলাদা করতে let
ব্যবহার করুন অথবা একটি ইমিডিয়েটলি-ইনভোকড ফাংশন ব্যবহার করুন।
1for (let i: number = 0; i < 3; i++) {
2 setTimeout((): void => {
3 console.log(i);
4 }, 1000);
5}
6// Output: 0, 1, 2
let
ব্যবহার করলে, প্রতিবার লুপ চালানোর জন্য i
-এর স্কোপ পৃথক হয় এবং প্রত্যাশিত ফলাফল পাওয়া যায়।
সারসংক্ষেপ
টাইপস্ক্রিপ্টে, টাইপ সিস্টেম ব্যবহার করে ক্লোজার দ্বারা আরও নিরাপদ ও পূর্বানুমানযোগ্য কোড তৈরি করা সম্ভব। সঠিকভাবে ক্লোজার ব্যবহার করলে ডাটা এনক্যাপসুলেশন এবং হায়ার-অর্ডার ফাংশনের নমনীয় ডিজাইন করা যায়। এছাড়াও, ক্লোজার ব্যবহারকালে মেমরি ম্যানেজমেন্ট ও অনাকাঙ্ক্ষিত স্কোপ রেফারেন্স সম্পর্কে সতর্ক থাকতে হবে।
আপনি আমাদের ইউটিউব চ্যানেলে ভিজ্যুয়াল স্টুডিও কোড ব্যবহার করে উপরের নিবন্ধটি অনুসরণ করতে পারেন। দয়া করে ইউটিউব চ্যানেলটিও দেখুন।