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

Mục đích bọc toàn bộ file JavaScript trong hàm vô danh (IIFE)

Việc bọc toàn bộ nội dung file JavaScript trong một hàm vô danh tự thi hành (IIFE - Immediately Invoked Function Expression):

(function() {
    // Toàn bộ code file ở đây
})();

có mục đích cốt lõi là: Tạo một scope riêng (private scope) để cách ly biến/hàm, tránh ô nhiễm Global Scope (window/global).

Tại sao cần thiết? (Vấn đề Global Scope)

Trong JavaScript (trước ES6), biến khai báo bằng var ở cấp độ cao nhất (top-level) của script sẽ trở thành thuộc tính của Global Object (window trên trình duyệt, global trên Node.js).

// file1.js
var config = { apiUrl: "..." }; // window.config

// file2.js (load sau)
var config = { theme: "dark" }; // GHI ĐÈ window.config! Lỗi logic.

IIFE giải quyết vấn đề như thế nào?

// file1.js
(function() {
    var config = { apiUrl: "..." }; // Chỉ tồn tại trong scope IIFE này
    // Code sử dụng config...
})();

// file2.js
(function() {
    var config = { theme: "dark" }; // Scope riêng, KHÔNG xung đột với file1
    // Code sử dụng config...
})();

Mỗi file có "vùng đất riêng" (scope), biến config không còn là global.

Lợi ích chính

Lợi íchGiải thích
Cách ly biến (Encapsulation)Biến cục bộ trong IIFE không truy cập được từ bên ngoài, tránh ghi đè/đọc nhầm.
Tránh xung đột tên (Namespace Collision)Nhiều thư viện/script cùng load trên 1 trang không lo biến trùng tên.
Quản lý phụ thuộc (Dependency Management)Truyền dependency vào IIFE như tham số: (function($, _) { ... })(jQuery, lodash); - bảo vệ khỏi thay đổi global.
Bảo mật thông tin (Information Hiding)Logic nội bộ, key API, thuật toán bí mật không bị lộ ra global console.
Tối ưu MinificationMinifier có thể rename biến cục bộ an toàn (ngắn gọn) mà không lo ảnh hưởng global.

Pattern phổ biến: Revealing Module Pattern

var MyLibrary = (function() {
    // Private
    var privateVar = 0;
    function privateMethod() { ... }

    // Public API
    function publicMethod() { ... }
    function anotherPublic() { ... }

    return {
        publicMethod: publicMethod,
        anotherPublic: anotherPublic
    };
})();

// Sử dụng
MyLibrary.publicMethod();
// MyLibrary.privateVar -> undefined (bảo vệ)

Trong thời đại ES6+ (Modern JS)

IIFE ít quan trọng hơn nhờ:

  • ES Modules (import/export): Mỗi file tự động là một module, scope riêng, không ô nhiễm global. Chuẩn hiện đại, khuyên dùng.
  • Block Scope (let/const): Biến không còn leo ra function scope.
  • Bundler (Webpack, Rollup, Vite...): Tự động wrap mỗi module trong IIFE (hoặc module wrapper) khi bundle cho production.

Khi nào vẫn dùng IIFE?

  • Code legacy (ES5), không dùng bundler/module.
  • Script nhúng trực tiếp trong HTML (<script>), không phải file module.
  • Polyfill, polyfill.io, script tracking (Google Analytics, Facebook Pixel...).
  • Bookmarklet, userscript (Tampermonkey).
  • Tạo scope tạm cho một khối code phức tạp trong function khác.

Tóm lại: Bọc file JS trong IIFE (function(){ ... })() nhằm tạo scope riêng, che giấu biến/hàm nội bộ, tránh xung đột global. Là pattern kinh điển (Module Pattern) trước thời ES Modules. Hiện nay ES Modules (import/export) là chuẩn thay thế tốt hơn.