在 JavaScript 中,閉包(Closure) 是指一個函數能夠記住並訪問它的詞法作用域(Lexical Scope),即使這個函數在其作用域之外被執行。閉包的特性使得它在以下情況下非常有用:
使用閉包模擬私有屬性,讓外部無法直接修改內部數據。
function createCounter() {
let count = 0; // 私有變量
return {
increment() {
count++;
},
decrement() {
count--;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.getCount()); // 0
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
counter.decrement();
console.log(counter.getCount()); // 1
使用閉包創建具有不同初始狀態的計數器。
function createCounter(initialValue) {
let count = initialValue;
return function () {
count++;
return count;
};
}
const counterA = createCounter(5);
const counterB = createCounter(10);
console.log(counterA()); // 6
console.log(counterA()); // 7
console.log(counterB()); // 11
console.log(counterB()); // 12
閉包在回調函數中保存上下文數據。
function fetchData(url) {
let cache = {};
return function () {
if (cache[url]) {
console.log("Fetching from cache:", cache[url]);
return cache[url];
} else {
console.log("Fetching from server...");
const data = `Data from ${url}`; // 模擬服務器數據
cache[url] = data;
return data;
}
};
}
const getUserData = fetchData("https://api.example.com/user");
console.log(getUserData()); // Fetching from server...
console.log(getUserData()); // Fetching from cache: Data from https://api.example.com/user
閉包讓函數變成更靈活的形式。
function multiply(a) {
return function (b) {
return a * b;
};
}
const double = multiply(2); // 創建一個函數,固定第一個參數為 2
const triple = multiply(3); // 創建一個函數,固定第一個參數為 3
console.log(double(4)); // 8
console.log(triple(4)); // 12
閉包可以讓事件處理器記住它綁定時的上下文。
function setupButtons() {
for (let i = 1; i <= 3; i++) {
document.getElementById(`button${i}`).addEventListener("click", function () {
console.log(`Button ${i} clicked!`);
});
}
}
在這裡,閉包使得每個事件處理器記住了綁定時的 i 值。
閉包適合用於: