1. 程式人生 > >JS筆記--探討閉包中內部函式在各情況下的可訪問範圍

JS筆記--探討閉包中內部函式在各情況下的可訪問範圍

         閉包是指有權訪問另一個函式作用域中的變數的函式,通過通過在一個函式中建立的另一個函式而獲得閉包。首先要說明的是,閉包並不等於匿名函式,匿名函式可以構成閉包,但不等於閉包。

         閉包的作用域,曾一直是困擾我多天的問題。為什麼在某些情況下,閉包只能訪問到外部函式的活動物件?而在某些情況下,閉包能訪問到整個作用域鏈上的每一個變數?具體的問題,要歸結於閉包是否被引用。

         當某個函式被呼叫時,會建立一個執行環境及相應的作用域鏈。

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。

         因此,請務必區分在呼叫內部函式時,外部函式是否已經結束了呼叫。一般情況下,若內部函式是作賦值處理,在呼叫時外部函式一般已經結束呼叫,此時只能使用活動物件;若內部函式是作直接呼叫處理,則能夠使用作用域鏈中的每一個變數。