IIFE 的全寫是 Immediately Invoked Function Expression,這是一個當你建立後就會立即執行的 function。通常都會是一次情而且是 anonymous 的。 ### 例子 IIFE 會是下面這樣 : ```js (() => console.log(‘Hello world’))(); ``` 這段 code 執行時,會立即畫出 Hello world 到你的 console 上。 ### 使用原因 使用 IIFE 的原因是為了保護變數的可用性。IIFE 中定義的變數不能從外部存取。這是編寫方法可以保護程式碼並減少出錯的方法。 ### 配入 function 的等性使用 另外你可能需要留位一個變數旳值,用來供日後存取用 (即類似於 factory pattern),可以看看以下例子 : ```js // 進行 10 for( let i=0; i<10; ++i ) { // 使用 setTimeout 來推遲執行 setTimeout(() =>{ // 記錄到 console console.log(i); }, 1000); } ``` 以上的代碼你可能會想看到 : 0,1,2,3,4,5,6,7,8,9 但是實際上你應該會看到是 : 9,9,9,9,9,9,9,9,9,9 這是因為經過 setTimeout 的 delay 後,`i` 的值已經由 0 數去到 9 了,所以當第一個 `setTimeout` 進行 `console.log(i)` 是,只會提取到 `i` 是 9 的結果。 `setTimeout` 只是一個例子,同樣的情況也會發生到 event handler 上,例如 : ```js // 取出所有 .button 的 div const elements = document.querySelectorAll('div.button'); // 每一個 element 也做一次 for( let i=0; i<elements.length; ++i ) { // 取出 element const element = elements[i]; // 加入 ‵click` 事件 element.addEventListener('click', function(evt) { // 記錄到 console console.log(i); }) } ``` 你按下任可的 `div.button` element 時,都只會在 console 出現 9。 #### 解決方法 你可以透過使用 IIFE 和變數傳入 function 的特性來避免這個事情。 ```js // 取出所有 .button 的 div const elements = document.querySelectorAll('div.button'); // 每一個 element 也做一次 for( let i=0; i<elements.length; ++i ) { // 取出 element const element = elements[i]; // IIFE (i2 => { // 加入 ‵click` 事件 element.addEventListener('click', function(evt) { // 記錄到 console console.log(i2); }) })(i); } ``` 通過把變數 `i` 傳入到 function 內,因為數值及文字是 [pass by value](https://www.google.com/search?q=js+pass+by+value) 的關係,所以在 function 內收到的變數 `i2` 是一個值,而不是 `i` 的參照 (reference),所以在之後應用 `i2` 時也只會得到當時 `i2` 值的結果。