JS-閉包 (Closure) 觀念整理

Chloe Lo
chloelo925
Published in
3 min readFeb 19, 2019

到底什麼是閉包?

為了搞懂閉包的觀念,研究了很多篇資料,似懂非懂困惑了好幾天,反問自己為什麼這樣寫不行,那樣寫會出錯?在感覺有點開竅的這個 moment,決定寫一篇來記錄現在的豁然開朗 😄。

觀念的詳盡解說來自於 MDN,但看第 1 ~ 2 遍的時候,會覺得像文言文,明明寫的是中文,卻只有挫折感 (os: 嗯…這到底在寫什麼?)

後來看了 Kuro 大大在 ithome 上寫的閉包文章,白話了很多,我終於看得懂中文了,感動 (誤)。

當內部 (inner) 函式被回傳後,除了自己本身的程式碼外,也可以 穿越 取得了內部函式「當時環境」的變數值,記住了執行當時的環境,這就是「閉包」。 (by Kuro)

用自己的話畫重點:

內部函式必須要用回傳 (return) 的方式,取得外部函式的變數 or 參數作運用。

閉包的用意在於 —
避免增加全域變數,但又能取得區域變數的值,取得的方法為 return 內部函式

from ithome by Kuro 大

此例的 return function(){return ++count} 即為閉包,var count = 0;為區域變數,但可以透過外部的呼叫,取得 count 的值,既沒有汙染到全域變數,也可以新增很多個變數 countFuc1.2.3.4….去取得各自作用域的 count 值出來。

var 的作用域 (scope) 最小單位是 function,不是 for (){ } 也不是 if (){ }

常會出錯的地方在 - 把 for 迴圈中的 i帶入迴圈中的內部函式,i 只會是以迴圈結束後最後的值帶入函式,無法累次帶進,原因就是 "var i 的作用域 (scope) 最小單位是 function,不是 for "。

以下方例子做解釋,i 的作用域在 setupHelp( )i 為全 "域" 變數,此域即為 setupHelp( ),在 i 進入showHelp ( )之前就會先把迴圈跑完,再將最後的值帶入 showHelp ( )永遠得不到想要的結果!

範例概念 from MDN 閉包

事情總是要有解決辦法,當遇到 for 迴圈時,有三種取得 i 值的方法

立即函式 (IIFE — Immediately Invoked Functions Expressions)

範例概念 from MDN 閉包

for 迴圈中,每跑一次 i 就會跑一次立即函式,也可以運用在 setTimeout()上,如下例:

from ithome by Kuro 大

內部的閉包函式用參數的方式送出給外層的另一個閉包

  • 寫法 1:
範例概念 from MDN 閉包
自己思考閉包邏輯時,發現容易寫錯的地方
  • 寫法 2:(外層閉包用立即函式)

var 換成 ES2015 的新關鍵字 let

let 的作用域 (scope)是{ } 區塊,e.g. if (){ } , for (){ } 都是,所以解決了原先 var 作用域在 function(){ }的問題!

--

--