一不小心就會犯錯

For loop 看似與 forEach() Higher Order Function 等效,但若用在使用 Empty Function 來 disable function 時,會有意想不到的結果出現。

Version


ECMAScript 2015

Introduction


1
2
3
4
5
6
7
let func = item => {
console.log(item);
func = () => {};
};

func('Sam');
func('Kevin');

由於 ECMAScript 是動態語言,甚至可以 disable 自己,只要將 empty function () => {} 指定給 variable 即可。

Imperative


disable000

  • 第二次執行 func() 時,已經是 undefined,因為已經成為 empty function 了
1
2
3
4
5
6
7
8
9
let func = item => {
console.log(item);
func = () => {};
};

const arr = [1, 2, 3];

for(let i = 0; i < arr.length; i++)
func(arr[i]);

連續使用 for loop 執行 3 次,也如預期只能印出 1,剩下都是 undefined

disable001

Functional


1
2
3
4
5
6
7
8
let func = item => {
console.log(item);
func = () => {};
};

const arr = [1, 2, 3];

arr.forEach(func);

我們都知道 for loop 可用 Functonal 的 forEach(),在不改變 func() 下改用 forEach()

disable002

  • 竟然出現令人驚訝的結果,forEach() 完整印出 123

Why Not ?


forEach() 理論上與 for loop 等效,且在 func() 完全沒改變的狀態下,為什麼結果完全不如預期呢 ?

For loop 的 Imperative 是一行一行執行,是在同一個 execution context 執行 func = () => {};,因此會影響接下來的執行。

forEach() 是傳入 function 定義,然後在各自的 execution context 執行 func = () => {};,因此不會互相影響,這也是為什麼 FP 沒有 Side Effect 的原因。

Conclusion


  • 將 function 指定成 empty function 雖然能達成自我 disable 的效果,但在 FP 下的 Higher Order Function 會無效,主要是因為 FP 是傳入 function 定義,然後在各自 execution context 執行,而不是如 Imperative 都在同一個 execution context 會有前後影響
2018-11-29