Ví dụ gốc minh họa khái niệm Closure (bao đóng) — một hàm nội bộ ghi nhớ biến của hàm bên ngoài ngay sau khi hàm ngoài đã thực thi xong. Đây là nền tảng của function factory và private state trong JavaScript.
Code gốc (đã sửa lỗi chính tả)
// Hàm ngoài (outer function)
var subtractMethod = function () {
var firstValue = 1000;
var thirdValue = 200; // Biến này không được dùng trong ví dụ
// Hàm trong (inner function) - tạo closure
var divideMethod = function () {
var secondValue = 500;
console.log("Kết quả divideMethod() = " + (firstValue / secondValue));
// Trả về phép trừ - dùng biến firstValue từ outer scope
return (firstValue - secondValue);
};
// Trả về chính hàm divideMethod (chưa gọi)
return divideMethod;
};
// Gọi subtractMethod() -> trả về hàm divideMethod
var result = subtractMethod(); // result giờ là hàm divideMethod
// Gọi hàm đã trả về
console.log("Kết quả subtractMethod() = " + result());
Chạy với Node.js
node ten_file.js
Kết quả
Kết quả divideMethod() = 2
Kết quả subtractMethod() = 500
Giải thích chi tiết
subtractMethod()chạy, tạo biến cục bộfirstValue = 1000.- Nó định nghĩa hàm
divideMethod— hàm này có quyền truy cậpfirstValue(lexical scoping). subtractMethodtrả vềdivideMethod(hàm), không gọi nó (không có dấu ngoặc).- Biến
resultnhận hàmdivideMethod. - Khi gọi
result():divideMethodchạy, tạosecondValue = 500.- In ra
1000 / 500 = 2. - Trả về
1000 - 500 = 500.
Tại sao đây là Closure?
Hàm divideMethod "đóng gói" (close over) biến firstValue từ phạm vi bên ngoài. Ngay cả khi subtractMethod đã kết thúc, firstValue vẫn sống trong bộ nhớ vì divideMethod vẫn tham chiếu đến nó.
Ứng dụng thực tế của Closure
1. Function Factory (Tạo hàm cấu hình)
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
2. Private State (Trạng thái riêng tư)
function createCounter() {
let count = 0; // Private - không truy cập trực tiếp từ ngoài
return {
increment: () => ++count,
decrement: () => --count,
getValue: () => count
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
console.log(counter.getValue()); // 2
// count không thể truy cập: counter.count // undefined
3. Module Pattern
const MyModule = (function() {
let privateVar = 'Bí mật';
function privateMethod() { console.log(privateVar); }
return {
publicMethod: function() { privateMethod(); }
};
})();
MyModule.publicMethod(); // "Bí mật"
Lưu ý quan trọng
- Closure tạo ra khi hàm được định nghĩa, không phải khi gọi.
- Mọi hàm trong JS đều là closure (vì đều có scope chain), nhưng thuật ngữ thường dùng cho hàm trả về/hàm callback giữ tham chiếu scope ngoài.
- Cẩn thận rò rỉ bộ nhớ (memory leak) nếu closure giữ tham chiếu lớn không cần thiết.