立即調用的函數表達式(IIFE)

在 Javascript 中,圓括號()是一種運算符,跟在函數名之後,表示調用該函數。比如,print()就表示調用print函數。

有時,我們需要在定義函數之後,立即調用該函數。這時,你不能在函數的定義之後加上圓括號,這會產生語法錯誤。

function(){ /* code */ }();
// SyntaxError: Unexpected token (

產生這個錯誤的原因是,function這個關鍵字即可以當作語句,也可以當作表達式。

// 語句
function f() {}

// 表達式
var f = function f() {}

爲了避免解析上的歧義,JavaScript 引擎規定,如果function關鍵字出現在行首,一律解釋成語句。因此,JavaScript 引擎看到行首是function關鍵字之後,認爲這一段都是函數的定義,不應該以圓括號結尾,所以就報錯了。

解決方法就是不要讓function出現在行首,讓引擎將其理解成一個表達式。最簡單的處理,就是將其放在一個圓括號裏面。

(function(){ /* code */ }());
// 或者
(function(){ /* code */ })();

上面兩種寫法都是以圓括號開頭,引擎就會認爲後面跟的是一個表示式,而不是函數定義語句,所以就避免了錯誤。這就叫做“立即調用的函數表達式”(Immediately-Invoked Function Expression),簡稱 IIFE。

注意,上面兩種寫法最後的分號都是必須的。如果省略分號,遇到連着兩個 IIFE,可能就會報錯。

// 報錯
(function(){ /* code */ }())
(function(){ /* code */ }())

上面代碼的兩行之間沒有分號,JavaScript 會將它們連在一起解釋,將第二行解釋爲第一行的參數。

推而廣之,任何讓解釋器以表達式來處理函數定義的方法,都能產生同樣的效果,比如下面三種寫法。

var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

甚至像下面這樣寫,也是可以的。

!function () { /* code */ }();
~function () { /* code */ }();
-function () { /* code */ }();
+function () { /* code */ }();

通常情況下,只對匿名函數使用這種“立即執行的函數表達式”。它的目的有兩個:一是不必爲函數命名,避免了污染全局變量;二是 IIFE 內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變量。

// 寫法一
var tmp = newData;
processData(tmp);
storeData(tmp);

// 寫法二
(function () {
  var tmp = newData;
  processData(tmp);
  storeData(tmp);
}());

上面代碼中,寫法二比寫法一更好,因爲完全避免了污染全局變量。

摘自 wangdoc.com,原文地址:https://wangdoc.com/javascript/types/function.html#立即調用的函數表達式(iife)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章