1. 程式人生 > >JS-立即執行函式表示式(IIFE)

JS-立即執行函式表示式(IIFE)

javascript函式呼叫

在javascript中,每一個函式在被呼叫的時候都會建立一個執行上下文,在該函式內部定義的變數和函式只能在該函式內部被使用,而正是因為這個上下文,使得我們在呼叫函式的時候能建立一些私有變數。

  • 先聲明後呼叫
// 宣告:
var foo = function(){ /* code */ };
// 呼叫:
foo();
  • 如果想不宣告直接呼叫
function(){ /* code */ }(); 
// 報錯:SyntaxError: Unexpected token (
// 執行到第一個左括號'('時報錯,因為函式函式應該有函式名而這裡沒有
  • 加上函式名再呼叫
function foo(){ /* code */ }(); 
// 報錯:SyntaxError: Unexpected token )
// 執行到倒數第一個右括號')'時報錯
// 因為()是提高優先順序的分組操作符,分組操作符內的表示式不能為空

使用立即執行函式(IIFE)

// 最常用的兩種寫法
(function(){ /* code */ }()); // 老道推薦寫法
(function(){ /* code */ })(); // 當然這種也可以
 
// 括號和JS的一些操作符(如 = && || ,等)可以在函式表示式和函式宣告上消除歧義
// 如下程式碼中,解析器已經知道一個是表示式了,於是也會把另一個預設為表示式
// 但是兩者交換則會報錯
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();
 
// 如果你不怕程式碼晦澀難讀,也可以選擇一元運算子
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
 
// 你也可以這樣
new function(){ /* code */ }
new function(){ /* code */ }() // 帶引數

《立即執行函式》還是《自執行函式》

IIFE的稱謂在現在似乎已經得到了廣泛推廣(不知道是不是原文作者的功勞?),而原文寫於10年,似乎當時流行的稱呼是自執行函式(Self-executing anonymous function),接下去作者開始為了說明立即執行函式的稱呼好於自執行函式的稱呼開始據理力爭,有點咬文嚼字,不過也蠻有意思的,我們來看看作者說了些什麼。

// 這是一個自執行函式,函式內部執行的是自己,遞迴呼叫
function foo() { foo(); }

// 這是一個自執行匿名函式,因為它沒有函式名
// 所以如果要遞迴呼叫自己的話必須用arguments.callee
var foo = function() { arguments.callee(); };

// 這可能也算是個自執行匿名函式,但僅僅是foo標誌引用它自身
// 如果你將foo改變成其它的,你將得到一個used-to-self-execute匿名函式
var foo = function() { foo(); };

// 有些人叫它自執行匿名函式,儘管它沒有執行自己,只是立即執行而已
(function(){ /* code */ }());

// 給函式表示式添加了標誌名稱,可以方便debug
// 但是一旦添加了標誌名稱,這個函式就不再是匿名的了
(function foo(){ /* code */ }());

// 立即執行函式也可以自執行,不過不常用罷了
(function(){ arguments.callee(); }());
(function foo(){ foo(); }());

我的理解是作者認為自執行函式是函式內部呼叫自己(遞迴呼叫),而立即執行函式就如字面意思,該函式立即執行即可。其實現在也不用去管它了,就叫IIFE好了。