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` 值的結果。