IIFE (Immediately Invoked Function Expression) - Hàm gọi ngay lập tức sau khi định nghĩa. Cú pháp đặc trưng: (function() { ... })().
Đặc điểm:
- Thực thi ngay lập tức (không cần gọi tên)
- Tạo **scope riêng** (function scope) - biến không lọt ra global
- Thường dùng để: encapsulation, tránh pollution global namespace, module pattern
- Có thể truyền tham số và nhận giá trị trả về
Ví dụ minh họa
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>IIFE JavaScript</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; padding: 20px; }
.sample { font-size: 18px; font-weight: 500; margin: 10px 0; color: #333; background: #f5f5f5; padding: 15px; border-radius: 4px; }
button { padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<h1>IIFE - Immediately Invoked Function Expression</h1>
<div class="sample" id="sample"></div>
<button id="btn">Chạy IIFE lại (demo closure)</button>
<script>
const sampleEle = document.querySelector("#sample");
// IIFE cơ bản - chạy ngay khi load trang
(function() {
sampleEle.innerHTML = "✅ IIFE chạy ngay lập tức khi định nghĩa!";
console.log("IIFE executed on load");
})();
// IIFE với tham số
(function(name, year) {
console.log(`Hello ${name}, năm ${year}`);
})("JavaScript", 2024);
// IIFE trả về giá trị (Module Pattern)
const Counter = (function() {
let count = 0; // Private variable
return {
increment: () => ++count,
decrement: () => --count,
getValue: () => count
};
})();
// Demo closure với IIFE
document.getElementById('btn').addEventListener('click', () => {
sampleEle.innerHTML += `
Counter: ${Counter.increment()}`;
});
// Arrow function IIFE (ES6)
(() => {
console.log("Arrow IIFE executed");
})();
// Async IIFE (top-level await alternative)
(async () => {
// const data = await fetch('/api/data');
console.log("Async IIFE ready");
})();
</script>
</body>
</html>
Kết quả
Trang load → Hiển thị: ✅ IIFE chạy ngay lập tức khi định nghĩa!
Nhấn nút → Tăng counter: 1, 2, 3... (biến count được bảo vệ trong closure)
Các biến thể IIFE:
// 1. Standard (khuyên dùng)
(function() { })();
// 2. Arrow function
(() => { })();
// 3. Unary operator (ít dùng)
!function() { }();
+function() { }();
~function() { }();
-function() { }();
void function() { }();
// 4. Với tham số
(function(window, $, undefined) {
// window, $ an toàn bên trong
// undefined đảm bảo thực sự là undefined (old IE)
})(window, jQuery);
// 5. Named IIFE (debugging stack trace)
(function myIIFE() {
// Có thể đệ quy: myIIFE()
})();
IIFE vs Block Scope (ES6+):
| Đặc điểm | IIFE | Block { } + let/const |
|---|---|---|
| Scope | Function scope | Block scope |
| Hoisting | Function declaration hoisted | let/const TDZ |
| Return value | Có thể return | Không |
| Async support | Dễ dàng (async IIFE) | Cần async function wrapper |
| Browser support | Tất cả (ES3+) | ES6+ (IE không hỗ trợ) |
Khi nào vẫn dùng IIFE (Modern JS):
- Top-level await (trước khi module hỗ trợ)
- Module pattern (private state)
- Code chạy ngay một lần (init, polyfill, benchmark)
- Tránh conflict global trong script tag không phải module
- Bookmarklet, userscript
Lưu ý:
- Trong ES Modules (
<script type="module">), top-level đã có scope riêng → ít cần IIFE - IIFE tạo function scope mới -
varbên trong không leak ra ngoài - Performance: IIFE tạo function object mới mỗi lần - tránh trong loop hot path