iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0

「閉包」只是函式記得自己出生時的環境。
理解這點,就能掌握閉包的核心。

什麼是閉包

在 JavaScript 裡,函式不只是執行一段程式而已。
它還會「帶著」當時可用的變數一起存在。
這代表函式即使被拿到別的地方執行,
仍能使用原本範圍裡的變數。

這種現象,就叫做 閉包(Closure)

  • 閉包就是「函式 + 定義當下的變數環境」。

閉包怎麼形成

閉包通常出現在以下情況:

  1. 一個外部函式裡面有一個內部函式。
  2. 內部函式使用了外部函式裡的變數。
  3. 外部函式執行後,內部函式被保留下來(例如被回傳或指定給變數)。

為什麼會有閉包

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

閉包在這裡幫我們看見了「作用域」的影響。
理解它,也就能更清楚地控制程式的執行行為。

參考資料


上一篇
Day25|作用域與 Hoisting
系列文
程式小白的 30 天轉職挑戰26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言