3月 10, 2024 Javascript
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` 值的結果。
過去文章
2025 (9)
4 (5)
3 (1)
2 (3)
2024 (25)
11 (3)
10 (3)
9 (1)
3 (18)
2022 (6)
10 (1)
6 (2)
5 (1)
3 (1)
1 (1)
2021 (21)
11 (7)
7 (1)
6 (2)
5 (2)
4 (6)
3 (2)
2 (1)
2020 (92)
12 (1)
11 (2)
10 (4)
9 (10)
8 (5)
7 (1)
6 (3)
5 (1)
4 (4)
3 (25)
2 (7)
1 (29)
2019 (57)
12 (25)
11 (7)
9 (25)