閉包是指有權訪問另一個函數作用域中的變量的函數,通過通過在一個函數中創建的另一個函數而獲得閉包。首先要說明的是,閉包並不等於匿名函數,匿名函數可以構成閉包,但不等於閉包。
閉包的作用域,曾一直是困擾我多天的問題。爲什麼在某些情況下,閉包只能訪問到外部函數的活動對象?而在某些情況下,閉包能訪問到整個作用域鏈上的每一個變量?具體的問題,要歸結於閉包是否被引用。
當某個函數被調用時,會創建一個執行環境及相應的作用域鏈。
1、當內部函數是在外部函數被調用的期間被調用的,則可以享受整個作用域鏈,並且得到的變量值都是即時的。
var k= 0;
functioncreateFunctions() {
for (var i=0; i<10; i++) {
(function() {
alert(k);
k++;
}) (); //這裏需要給內部函數加個模仿塊級作用域處理,不然無法即時調用該函數。
};
}
createFunctions();
以上JS代碼得到的結果是0~9。這說明了內部函數實時的調用了全局變量K並改變了它的值,同時能夠實時的得出結果。
2、內部函數並非在外部函數被調用時執行,而是在外部函數結束後才執行。換句話說,內部函數是被引用的,而非被直接調用的。這時,內部函數只能調用外部函數的活動對象(即外部函數各變量的最終值)。
function createFunctions(){
var result =new Array();
for (vari=0; i < 5; i++) {
result[i] =function(){
return i;
};
/*在此,我們把函數賦值給數組result,並期待數組result返回i在每個時段的數值。但結果result的每一個值都是指向內部函數的指針。*/
}
returnresult;
}
var funcs =createFunctions();
/*在這裏funcs得到了數組result的賦值。在使用funcs數組時,因爲外部函數createFunctions已經結束了調用,因此只能留下自身的活動對象供以自身的內部函數調用。因此,funcs中的每一個值都是i的最終結果,即5*/
for(var i=0;i < funcs.length; i++){
document.write(funcs[i]() + "<br />");
}
在標註的部分,我們將內部函數賦值到result中。之後,在funcs中得到了函數的返回值result。實際上,funcs和result中全是對內部函數的指針。在使用funcs數組時,內部函數被調用(引用),然而createFunctions()早在創建funcs完畢後便結束調用,因此只留下自身本地活動對象給內部函數調用。此時的i爲5,所以funcs得到的結果也全部是5。
因此,請務必區分在調用內部函數時,外部函數是否已經結束了調用。一般情況下,若內部函數是作賦值處理,在調用時外部函數一般已經結束調用,此時只能使用活動對象;若內部函數是作直接調用處理,則能夠使用作用域鏈中的每一個變量。