JS筆記--探討閉包中內部函式在各情況下的可訪問範圍
阿新 • • 發佈:2019-02-16
閉包是指有權訪問另一個函式作用域中的變數的函式,通過通過在一個函式中建立的另一個函式而獲得閉包。首先要說明的是,閉包並不等於匿名函式,匿名函式可以構成閉包,但不等於閉包。
閉包的作用域,曾一直是困擾我多天的問題。為什麼在某些情況下,閉包只能訪問到外部函式的活動物件?而在某些情況下,閉包能訪問到整個作用域鏈上的每一個變數?具體的問題,要歸結於閉包是否被引用。
當某個函式被呼叫時,會建立一個執行環境及相應的作用域鏈。
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。
因此,請務必區分在呼叫內部函式時,外部函式是否已經結束了呼叫。一般情況下,若內部函式是作賦值處理,在呼叫時外部函式一般已經結束呼叫,此時只能使用活動物件;若內部函式是作直接呼叫處理,則能夠使用作用域鏈中的每一個變數。