JS詞法做用域

1.由變量開始談
習慣性先來段代碼:
var x = "globol value";
var getValue = function(){
    alert(x);    //彈出"undefined"
    var x = "local value";
    alert(x);    //彈出"local value";
}
getValue();
代碼很簡單,首先定義了一個全局變量x並賦了初值,而後寫了個getValue的方法,以後咱們用alert彈出x的值,可是結果是undefined,不是global value也不是local value,這個咱們可能會感受到奇怪。其實理解這個問題的關鍵就是要清楚x的做用域。
第一個var x中的x是全局變量,js解釋器在執行任何代碼以前會先建立一個全局對象(global object),全局變量就是至關於這個全局對象的一個屬性。同理,對於getValue這個函數,就會生成一個叫作調用對象的東西,局部變量就是這個調用對象的屬性,例子中第二個var x中的x就是局部變量。
2.詞法做用域
詞法做用域。這個是何方神聖呢?要理解的話,其實咱們能夠對比傳統面向對象的(如JAVA、C#)中的變量的做用域,咱們知道C#中的變量做用域是塊級的,即這個變量只能活動在定義他的一個直接外界內,如if子句內,for子句內定義的變量外界是沒法讀取的。而js中呢,變量卻不是這樣的,在同一個函數內定義的變量其它的成員是能夠訪問的。看個例子會清楚不少:
function test(o){
    var i = 0;
    if(typeof o == "object"){
        var j = 0;
        for(var k=0; k < 10; k++){
            document.write(k);
        }
        document.write(k);            //k是能夠被訪問到的,即便它在for子句外
    }
    document.write(j);                //說明j是能夠被訪問到的,即便它在if子句外
}
清楚了這一點後,就來理解下js中關於詞法做用域的含義。
當定義了一個函數後,當前的做用域就會被保存下來,而且成爲函數內部狀態的一部分,這個是很重要的一個概念。
下面咱們回到開篇的那個例子,當getValue函數被定義的時候,他的做用域被保存起來,還有被加到做用域鏈上,他的上端就是全局執行環境。當調用getValue方法的時候,js解釋器首先會把做用域設置爲定義函數的時候的那個做用域(即以前保存那個),接下來,他在做用域的前加上調用對象即getValue這個函數,再在他的上端加上全局對象。以下圖:閉包


這個做用域鏈其實和原型鏈有點類似,也好似在本做用域內找不到就會向上去找。比方說開篇那個例子,找x的時候(js的預約義機制,就是js解釋器會先對var定義的變量進行初始化,應該說只是起了定義的做用但沒賦值),會先在本做用域內找,由預約義機制知能夠找到x,可是沒賦值,因此是undefined值。知道了這點咱們來知道開篇那個代碼實際上是等價於下面這個的:
var x = "globol value";
var getValue = function(){
    var x;
    alert(x);    //彈出"undefined"
    x = "local value";
    alert(x);    //彈出"local value";
}
getValue();
當調用 getValue()函數時造成的做用域鏈爲「調用對象」->「全局對象」,執行alert(x)時,首先查找調用對象是否有x的屬性,若是有則使用「調用對象」的x,若是沒有,就接着查找「全局對象」是否有x的屬性。
實際上js解釋器作的事情應該是按以上這個例子執行的,因此從另外一個角度說,將變量的定義放在開頭這個約定是有意義而且有益處的。
3.延伸
清楚了以上關於詞法做用域的概念後,咱們就不難理解閉包的概念了,它只是用到了做用域鏈的不可向下性,即下面的做用域能夠訪問上面的,但上面的不能夠訪問下面的。固然這只是構成閉包的一個條件,閉包更重要的仍是外部函數持有內部函數的一個嵌套函數的引用,看下簡單例子:
function foo(){
    var age = 10;
    function boo(){
        age += 10;
        return age;
    }
    return boo;
}
alert(foo()());    //20函數

//var tx = foo();
//alert(tx());    //20spa

相關文章
相關標籤/搜索