0%

JavaScript IIFE 立即呼叫函式

IIFE 是立即被呼叫的函式的簡寫,全名為 Immediately Invoked Function Expression。在 ES6 之前,JavaScript 變數有效範圍的最小單位以 function 為分界。
IIFE 的好處,就是可以減少「全域變數」的產生,同時也避免了變數名稱衝突的機會。

IIFE 語法

將一個正常的函式包在()裡,後面加個()就成了匿名函式。
後面的()表示立即執行,也可帶參數。

1
2
3
4
5
6
7
8
9
// 一般的函式
function doSomething(i) {
// 做一些事...
}

// IIFE函式
(function() {
// 做一些事....
})();

IIFE 函式前面一定要有; 不然會有錯誤
範例:

1
2
3
4
var foo = 'foo';
(function(bar) {
Console.log(bar);
})(foo);

匿名函數的參數(foo)就是 var foo 的這個變數,如果匿名函數有兩個參數, 後面的() 也可帶兩個參數

一般呼叫函式的方式可以是:

1
2
3
4
5
doSomething(123);
// 匿名函式
(function doSomething(i) {
// 做一些事...
})(123);

使用匿名函式即是馬上使用,也就是宣告他的同時也呼叫它,自然就不需要給名字了。所以就成了以下不需名字的函式。

1
2
3
(function(i) {
// 做一些事...
})(123);

在回圈內呼叫 function 會需要用 IIFE 來把參數的值保留起來,如果有看過 jQuery 的原始碼,會發現有這段:

1
2
3
(function(window, undefined) {
// ....
})(window);

jQuery 也用了相同的手法將 window 和 indefined 保留起來。
ES6 以後新增了 let 與 const 的變數型態,且改以 { } 作為它的 Scope。換句話說,將範例中的 for 的 var 改為以 let 宣告就可以做到保留 i 在執行迴圈當下的「值」的效果:

經典迴圈非同步問題

1
2
3
4
5
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, i * 1000);
}

目的:每一秒列出一個 i
但會列印出10個10,因為當進入列印迴圈時,i 已經跑到10了
解決如何因非同步而無法印出1-10的方法:使用 IIFE 和閉包
使用 IIFE

1
2
3
4
5
6
7
for (var i = 0; i < 10; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, j * 1000);
})(i);
}

參考:立即被呼叫的函式 (Immediately Invoked Function Expression, IIFE)