Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Self-Invoking Function (IIFE) trong JavaScript

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ểmIIFEBlock { } + let/const
ScopeFunction scopeBlock scope
HoistingFunction declaration hoistedlet/const TDZ
Return valueCó thể returnKhông
Async supportDễ dàng (async IIFE)Cần async function wrapper
Browser supportTấ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 - var bê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