在C/C++中,由花括弧封閉的代碼塊都有自己的範圍,也就是塊級範圍(私人範圍)。而在javascript中則沒有塊級範圍,首先來看一段代碼:
for(var i=0;i<10;i++){
}
alert(i);
執行結果是:
10
對於有塊級範圍的語言來說,for語句中定義並初始化的變數i在迴圈外是無法訪問的,而在javascript中,for語句中定義的變數i在迴圈結束後,依舊會存在於迴圈外部的執行環境(範圍)中,在這裡i的範圍是全域環境。具體來說就是:使用var關鍵字聲明變數時,這個變數會自動添加到距離最近的可用環境中。對於函數而言,這個最近的環境就是函數的局部環境。如果變數在未經聲明的情況下被初始化,則該變數會被自動添加到全域環境。
不過有時候的確很需要塊級範圍來解決一些問題,這時候我們就可以使用匿名函數來模仿塊級範圍。
匿名函數就是沒有名字的函數,有時候也被稱為拉姆達(lamda)函數。形式如下:
function functionName(arg0,arg1){
//函數體
}
而用作模仿塊級範圍(私人範圍)的匿名函數的文法形式如下:
(function(){
//塊級範圍
})();
以上代碼的意思是:首先定義並立即調用一個匿名函數。將函式宣告包含在圓括弧中,表示它實際上是一個函數運算式。而緊隨其後的另一對圓括弧表示立即調用這個函數。
可能剛開始我們感覺這種文法比較難以理解,我們可以先看下下面這段代碼:
var myFunc=function(){
alert(‘函數’);
};
myFunc();
上面的代碼中,首先以函數運算式的方式定義了一個函數,然後立即調用它。在這裡定義函數的方式就是先建立一個匿名函數,然後將其賦值給變數myFunc,而在函數名稱後加一對圓括弧即表示調用函數。那我們如果直接用匿名函數代表變數myFunc,在匿名函數後面添加一對圓括弧不就表示直接調用了嗎?然而,如果如下這樣做就會報錯:
function(){
//塊級範圍
}();
因為在javascript中,function關鍵字表示一個函式宣告的開始,而函式宣告後面不能直接跟圓括弧。而函數運算式後面可以跟圓括弧,來表示函數調用。在函式宣告外面加一對圓括弧就可以轉換成函數運算式,如下:
(function(){
//塊級範圍
})();
這樣最簡單的塊級範圍就建立好了。這種技術長在全域範圍中用在函數外部,來限制向全域範圍中添加過多的變數和函數。例如:
(function(){
var now=new Date();
if(now.getMonth()==0&&now.getDate()==1){
alert(“Happy new year”);
}
})();
以上代碼放在全域範圍中,用來確定在1月1日顯示一條祝賀新年的資訊。其中變數now現在就是匿名函數模仿的塊級範圍中的局部變數。
當然,只要我們臨時需要一些變數,都可以使用塊級範圍(私人範圍)。當匿名函數執行完畢,其範圍鏈立即銷毀,從而可以減少閉包佔用資源問題。