標籤:
×目錄[1]實現 [2]用途前面的話
嚴格來講,IIFE並不是閉包,因為它並不滿足函數成為閉包的三個條件。但一般地,人們認為IIFE就是閉包,畢竟閉包有多個定義。本文將詳細介紹IIFE的實現和用途
實現
函數跟隨一對圓括弧()表示函數調用
//函式宣告語句寫法function test(){};test();//函數運算式寫法var test = function(){};test();
但有時需要在定義函數之後,立即調用該函數。這種函數就叫做立即執行函數,全稱為立即調用的函數運算式IIFE(Imdiately Invoked Function Expression)
[注意]javascript引擎規定,如果function關鍵字出現在行首,一律解釋成函式宣告語句
【1】函式宣告語句需要一個函數名,由於沒有函數名,所以報錯
//SyntaxError: Unexpected token (function(){}();
【2】函式宣告語句後面加上一對圓括弧,只是函式宣告語句與分組操作符的組合而已。由於分組操作符不可為空,所以報錯
//SyntaxError: Unexpected token )function foo(){}();//等價於function foo(){};();//SyntaxError: Unexpected token )
【3】函式宣告語句加上一對有值的圓括弧,也僅僅是函式宣告語句與不報錯的分組操作符的組合而已
function foo(){}(1);//等價於function foo(){};(1);
所以,解決方案就是不要讓function出現在行首,讓引擎將其理解成一個運算式
最常用的兩種辦法
(function(){ /* code */ }()); (function(){ /* code */ })();
其他寫法
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一般用於構造私人變數,避免全域空間汙染
接下來用一個需求實現來更直觀地說明IIFE的用途。假設有一個需求,每次調用函數,都返回加1的一個數字(數字初始值為0)
【1】全域變數
一般情況下,我們會使用全域變數來儲存該數字狀態
var a = 0;function add(){ return ++a;}console.log(add());//1console.log(add());//2
【2】自訂屬性
但上面的方法中,變數a實際上只和add函數相關,卻聲明為全域變數,不太合適。
將變數a更改為函數的自訂屬性更為恰當
function add(){ return ++add.count;}add.count = 0;console.log(add());//1console.log(add());//2
【3】IIFE
其實這樣做,還是有問題。有些代碼可能會無意中將add.count重設
使用IIFE把計數器變數儲存為私人變數更安全,同時也可以減少對全域空間的汙染
var add = (function(){ var counter = 0; return function(){ return ++counter; }})();console.log(add())//1console.log(add())//2
深入理解閉包系列第三篇——IIFE