Trước ES6
- Chưa có
let,const→varkhông có block scope - Chưa có module → dùng IIFE để tạo private scope
- IIFE là cách duy nhất để đóng gói code
IIFE (Immediately Invoked Function Expression) là một function expression được định nghĩa và gọi ngay lập tức tại chỗ, không cần đặt tên rồi gọi ở dòng khác.
(function () { console.log("Chạy ngay!");})();(function () { // code chạy ngay})();(() => { // code chạy ngay})();(async () => { const data = await fetch('/api'); console.log(data);})();(function (name) { console.log(`Hello, ${name}!`);})("An");// "Hello, An!"var x = 1;
(function () { var x = 2; // x chỉ tồn tại trong IIFE console.log("Trong IIFE:", x); // 2})();
console.log("Ngoài IIFE:", x); // 1 ← không bị ảnh hưởngvar x = 1;
// Không có IIFE → var x bị ghi đèvar x = 2;
console.log(x); // 2 ← biến global bị thay đổi!const counter = (function () { let count = 0; // "private" — không truy cập được từ bên ngoài
return { inc() { count++; return count; }, get() { return count; }, };})();
console.log(counter.inc()); // 1console.log(counter.inc()); // 2console.log(counter.get()); // 2console.log(counter.count); // undefined — không truy cập được!// Mỗi thư viện tự bọc trong IIFE → không xung đột biến(function ($) { // $ ở đây chắc chắn là jQuery $(".btn").click(function () { ... });})(jQuery);Trước ES6
let, const → var không có block scopeSau ES6
let, const có block scope → dùng {} là đủimport/export) thay thế IIFE(function () { var secret = 42; console.log(secret);})();// secret không tồn tại ở đây{ const secret = 42; console.log(secret);}// secret không tồn tại ở đâyconst secret = 42;export const getSecret = () => secret;
// main.jsimport { getSecret } from './utils.js';// secret không truy cập trực tiếp đượcNgoài cách phổ biến nhất, còn có vài cách viết khác (ít dùng):
// Cách 1: phổ biến nhất(function () { ... })();
// Cách 2: gọi bên trong ()(function () { ... }());
// Cách 3: dùng toán tử unary!function () { ... }();void function () { ... }();+function () { ... }();| Đặc điểm | Chi tiết |
|---|---|
| Cú pháp | (function () { ... })(); hoặc (() => { ... })(); |
| Mục đích | Tạo scope riêng, closure, dữ liệu private |
| Tham số | Truyền qua () cuối cùng |
| Async | (async () => { ... })(); |
| Thay thế hiện đại | let/const block scope, ES Modules |
| Vẫn hữu ích | Async IIFE, tương thích legacy, đóng gói nhanh |