IIFE জাভাস্ক্রিপ্টের অন্যতম জনপ্রিয় একটি ডিজাইন প্যাটার্ন। এটি ইফি বলেই উচ্চারণ করে। IIFE জাভাস্ক্রিপ্ট কমিউনিটি দীর্ঘদিন ধরে ব্যবহার করে আসছে কিন্তু এর মিসলিডিং শব্দটি ছিল "সেলফ-এক্সিকিউটিং এনোনিমাস ফাংশন" যা পরবর্তীতে Ben Alman এটির একটি উপযুক্ত নাম দিয়েছেন "IIFE"। আজকে এটার সম্পর্কে বিস্তারিত লেখার চেষ্টা করবো।
IIFE - এর পূর্ণরুপ হচ্ছে Immediately Invoked Function Expression। IIFE হল একটি ফাংশন যা একটি এক্সপ্রেশন হিসাবে ডিক্লেয়ার এবং ডিক্লেয়ারেশনের পরপরই এক্সিকিউট করা হয়।
নিম্নলিখিত সিনট্যাক্স দেখায় কিভাবে IIFE ডিফাইন করতে হয়ঃ
(function () {
// code goes here...
})();
আপনি arrow function
ব্যবহার করেও IIFE ডিফাইন করতে পারবেন।
(() => {
// code goes here...
})();
যখন আপনি একটি ফাংশন ডিফাইন বা ডিক্লেয়ার করেন, জাভাস্ক্রিপ্ট ইঞ্জিন গ্লোবাল অবজেক্টের সাথে ফাংশনকে যোগ করে। একইভাবে, যদি আপনি ফাংশনের বাইরে একটি ভেরিয়েবল ডিক্লেয়ার করেন, জাভাস্ক্রিপ্ট ইঞ্জিন ঐ ভেরিয়েবলকে গ্লোবাল অবজেক্টের সাথে যোগ করে। নিম্নলিখিত উদাহরণ দেখুনঃ
var num = 7;
function sum(a, b) {
return a + b;
}
console.log(window.sum); /**
ƒ sum(a,b) {
return a + b;
}
*/
console.log(window.num); // 7
যদি আপনার প্রোগ্রামে অনেক গ্লোবাল ভেরিয়েবল এবং ফাংশন থাকে, তাহলে আপনার প্রোগ্রাম ইনইফিশিয়েন্টলি মেমরি ব্যবহার করতে পারে এবং আপনার গ্লোবাল ভেরিয়েবল এবং ফাংশনগুলি অন্য কোন লাইব্রেরীর সাথে কনফ্লিক্ট করতে পারে যদি ঐ লাইব্রেরীতে একই নামে ভেরিয়েবল এবং ফাংশন থাকে। ফাংশন এবং ভেরিয়েবলগুলিকে গ্লোবাল অবজেক্ট কনফ্লিক্ট করা থেকে বিরত রাখার একটি উপায় হল IIFE ব্যবহার করা।
(function domeSomeMagic() {
// code goes here...
})();
(function () {
// code goes here...
})();
এই সিনট্যাক্সে, দুই বা ততোধিক জাভাস্ক্রিপ্ট ফাইলকে একক ফাইলে বান্ডল করার জন্যে স্টেটমেন্টটি শেষ করতে সেমিকোলন ব্যবহার করা হয়। উদাহরণস্বরূপ, আপনার দুটি ফাইল আছে file1.js এবং file2.js যা IIFE ব্যবহার করে।
/**
* file1.js
*/
(function () {
// ...
})();
/**
* file2.js
*/
(function () {
// ...
})();
যদি আপনি একটি কোড বান্ডলার টুল ব্যবহার করে উভয় ফাইলগুলির কোডকে একটি একক ফাইলের কোড কনক্যাট করতে চান সেমিকোলন (;) ছাড়া, কনক্যানেটেড কোডটি একটি Uncaught TypeError: (intermediate value)(...) is not a function
সিনট্যাক্স ইরোর দিবে।
ধরুন আপনার নিম্নলিখিত ফাংশন সহ math.js নামে একটি লাইব্রেরি আছে এবং একটি HTML ফাইলে math.js লোড করুনঃ
function add(a, b) {
return a + b;
}
function sub(a, b) {
return a - b;
}
function mult(a, b) {
return a * b;
}
function div(a, b) {
return a / b;
}
পরবর্তীতে, আপনি একই ফাইলে anotherLibrary.js নামে আরেকটি জাভাস্ক্রিপ্ট লাইব্রেরি লোড করতে চানঃ
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>JavaScript IIFE</title>
</head>
<body>
<script src="math.js"></script>
<script src="anotherLibrary.js"></script>
<script src="app.js"></script>
</body>
</html>
anotherLibrary.js
লাইব্রেরীতেও sub()
নামে ফাংশন রয়েছে যেটি একটি স্ট্রিং রিটার্ন করেঃ
function sub() {
return "sub";
}
যখন আপনি app.js
ফাইলে sub()
ফাংশনটি ব্যবহার করবেন, তখন এটি দুটি সংখ্যার বিয়োগের পরিবর্তে sub স্ট্রিং রিটার্ন করবেঃ
let result = sub(30, 20);
console.log(result); // sub
কারণ anotherLibrary.js এর sub() ফাংশন math.js লাইব্রেরির sub() ফাংশনকে ওভাররাইড করে ফেলছে।
এই সমস্যা ঠিক করতে, আপনি math.js এ IIFE ব্যবহার করতে পারেনঃ
var math = (function () {
function add(a, b) {
return a + b;
}
function sub(a, b) {
return a - b;
}
function mult(a, b) {
return a * b;
}
function div(a, b) {
return a / b;
}
return {
add: add,
sub: sub,
mult: mult,
div: div,
};
})();
IIFE math
নামে একটি অবজেক্ট রিটার্ন করে যাতে add
, sub
, mult
, এবং div
মেথড হয়েছে।
app.js
ফাইলে, আপনি math.js
লাইব্রেরি নিম্নলিখিতভাবে ব্যবহার করতে পারেনঃ
var result = math.sub(30, 20);
console.log(result); // 10
console.log(sub()); // sub
প্রথম sub() ফাংশনকে math.sub() দিয়ে ইনভোক করা হয়েছে যেটি math.js থেকে এক্সপোর্ট করা অন্যদিকে দ্বিতীয় sub() ফাংশনকে anotherLibrary.js থেকে ইনভোক করা হয়েছে।
- অপ্রয়োজনীয় গ্লোবাল ভেরিয়েবল এবং ফাংশন তৈরি করে না।
- IIFE তে ডিফাইন করা ফাংশন ও ভেরিয়েবল অন্য ফাংশন এবং ভেরিয়েবলের সাথে কনফ্লিক্ট করে না। এমনকি তাদের একই নাম থাকলেও।
- জাভাস্ক্রিপ্টের কোড অর্গানাইজ করে।
- জাভাস্ক্রিপ্ট কোড মেইন্টানাবল করে।