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

Cấu trúc (function() { })() trong JavaScript là gì? (IIFE)

Cấu trúc (function() { })() được gọi là IIFE - Immediately Invoked Function Expression (Biểu thức hàm gọi ngay lập tức). Đây là một hàm vô danh (anonymous function) được định nghĩa và thực thi ngay tại chỗ, chỉ chạy một lần.

Cú pháp phân tích

(function() { 
    // code bên trong - scope riêng
})();
  1. (function() { ... }): Cặp ngoặc đơn bên ngoài biến "Function Declaration" thành "Function Expression" (biểu thức hàm). Trình duyệt hiểu đây là một giá trị (expression), không phải câu lệnh khai báo.
  2. (): Cặp ngoặc đơn bên trong (sau) là toán tử gọi hàm (invocation operator), thực thi hàm biểu thức ngay lập tức.

Ví dụ minh họa

// 1. IIFE cơ bản
(function() {
    var privateVar = "Tôi là biến cục bộ";
    console.log(privateVar); // "Tôi là biến cục bộ"
})();

// 2. IIFE với tham số
(function(name, age) {
    console.log("Xin chào " + name + ", " + age + " tuổi");
})("An", 25); // "Xin chào An, 25 tuổi"

// 3. IIFE trả về giá trị (Module Pattern)
var Counter = (function() {
    var count = 0; // Private variable
    return {
        increase: function() { count++; console.log(count); },
        decrease: function() { count--; console.log(count); },
        getCount: function() { return count; }
    };
})();

Counter.increase(); // 1
Counter.increase(); // 2
console.log(Counter.getCount()); // 2
// count không thể truy cập từ bên ngoài: Counter.count = undefined

Tại sao dùng IIFE? (Lợi ích chính)

  • Tạo Scope riêng (Encapsulation): Biến/ hàm bên trong không rò rỉ ra global scope (window trong trình duyệt). Tránh xung đột tên biến.
  • Module Pattern: Trả về object chứa các method public, che giấu state(private variable) - nền tảng của module JS trước ES6.
  • Khởi tạo một lần (Initialization): Chạy code setup ngay khi load script (polyfill, config, event listener...).
  • Tránh ô nhiễm Global Scope: Quan trọng trong môi trường nhiều script (jQuery, plugin, analytics...).

Các biến thể cú pháp IIFE

// Cách 1: Crockford (Phổ biến, khuyên dùng)
(function() { /* code */ }());

// Cách 2: Đóng ngoặc bao hàm + gọi
(function() { /* code */ })();

// Cách 3: Toán tử unary (ngắn gọn, dùng cho minify)
+function() { /* code */ }();
!function() { /* code */ }();
~function() { /* code */ }();
void function() { /* code */ }();

// Cách 4: Arrow function IIFE (ES6+)
(() => { /* code */ })();

Lưu ý quan trọng

  • Luôn kết thúc IIFE bằng dấu chấm phẩy (;) nếu dòng sau bắt đầu bằng (, [, /, +, - để tránh lỗi ASI (tự động chèn dấu chấm phẩy sai).
  • IIFE không tạo closure nếu không trả về hàm/object tham chiếu biến nội bộ (như ví dụ Counter).
  • Tên hàm trong IIFE (Named IIFE) hữu ích cho debug stack trace: (function myIIFE() {})().
  • Trong ES6+, hãy ưu tiên Module (import/export) và Block Scope (let/const) thay vì IIFE.

Tóm lại: (function(){})() là IIFE - kỹ thuật kinh điển tạo scope riêng, đóng gói module, tránh xung đột global trong JS ES5. Vẫn hữu ích trong legacy code, polyfill, hoặc khởi tạo nhanh.