「閉包」只是函式記得自己出生時的環境。
理解這點,就能掌握閉包的核心。
在 JavaScript 裡,函式不只是執行一段程式而已。
它還會「帶著」當時可用的變數一起存在。
這代表函式即使被拿到別的地方執行,
仍能使用原本範圍裡的變數。
這種現象,就叫做 閉包(Closure)。
閉包通常出現在以下情況:
JavaScript 採用「詞法作用域」(Lexical Scope),
閉包讓 JavaScript 的函式更有彈性。
可以說,閉包是讓 JavaScript 能寫出「有記憶的程式」的關鍵。
閉包最常見的應用,就是「保存資料」。
例如以下這段程式,建立了一個能記住計數的函式:
function createCounter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3
count 是 createCounter 裡的變數,
但透過閉包,它在外部仍被記得並持續累加。
這種特性常被用來實作「模擬私有變數」或「模組化」的效果。
閉包有時也會造成意外的結果。
最常見的例子,是在迴圈中使用 var 時:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 結果:3、3、3
因為 var 沒有區塊作用域,三個函式共用同一個變數 i。
若改用 let,每次迴圈都會建立新的變數範圍:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 結果:0、1、2
閉包在這裡幫我們看見了「作用域」的影響。
理解它,也就能更清楚地控制程式的執行行為。