什麼是 IIFE?
當迴圈遇到setTimeout()
假設想透過迴圈 + setTimeout()
來做到,在五秒鐘之內,每秒鐘依序透過 console.log 印出: 0 1 2 3 4
我們會直覺的寫下
1 |
|
印出來的結果是5個5。
為什麼不是1,2,3,4,5呢???
因為
JavaScript 是一個「非同步」的語言,所以當我們執行這段程式時, for
迴圈並不會等待window.setTimeout()
結束後才繼續。
而是在執行階段就一口氣就把他跑完。
所以for
迴圈在開始執行的第一個瞬間(0的時候),就把五次的window.setTimeout()
跑完。然後跑到1時,全部把5印出來。
要如何避免這個問題呢?
可以利用「切分變數有效範圍的最小單位是function
」這個特性,把window.setTimeout()
透過一個「立即被呼叫的特殊函式」來包裝。
像是這樣寫
1 |
|
下面來解釋這個這個神奇的寫法
- 先加個小括號
()
把這個函式包起來
1 |
|
- 因為要呼叫它,所以在後面再加個小括號
()
1 |
|
- 比對一下
一般呼叫函式
1 |
|
函式宣告當下即呼叫
1 |
|
可以很清楚的了解,立即函數,就如其名,它要馬上被執行。
解決window.setTimeout
問題
回到for
迴圈與window.setTimeout
的問題。
1 |
|
我們知道像上面這樣的寫法,在執行window.setTimeout
的時候, i
早已變成了5。
那麼為了可以保留每一次執行迴圈時,那個「當下的」i
,我們可以用一個立即被呼叫的特殊函式將它包覆起來,然後將i
作為參數傳入:
1 |
|
印出的結果就會是我們要的1,2,3,4,5
封裝
廣義來說,IIFE也是儲存閉包的環境狀態的作法,在執行 setTimeout()
的同時,會將當下的 i 鎖起來,延長它的生命。
在Alex宅幹嘛的直播裡,31.28s 有提到封裝的概念,寫Jquery第一件事情先處理scope,不處理的話name
會被註冊在window
上面,任何人都可以去讀取,使用,覆蓋我寫的資料。
以一般來說
1 |
|
在開發人員工具可以直接讀取到name
而scope就是開一個密閉的空間,寫在裡面,不給別人看到。
1 |
|
使用立即函式封裝
封裝後就讀取不到了
參考文章
本筆記參考以下文章加上自己所理解出來的內容撰寫。