JavaScript with語句的理解

    今天看到js的with語句部分,書中寫到,with語句接收的對象會添加到作用域鏈的前端並在代碼執行完之後移除。看到這裏,我有兩點疑問,添加到作用域鏈前端是不是指對象會被放置到作用域鏈的最底部,然後查找變量時最先查找這個對象(按照我的理解,js的作用域鏈查找變量的過程是一個冒泡的過程,底部開始往上走,找到了就停止冒泡),第二點就是,執行之後移除是不是指with語句之後就移除那個對象。於是寫了一個簡單的例子來驗證一下。

var b = {a:2};

function sayA(){
    var a = 1;
    with(b){alert(a);}
    alert(a);
}

sayA();

    代碼運行結果是2和1。這證實了我之前的猜想,因爲正常情況,位於作用域鏈底部的應該是函數的局部變量a,然而with語句中的a卻是對象b的字段a,這證明對象b佔據了作用域鏈中最底部的位置。而with語句之後的a的值又變成了1,說明對象b已從作用域鏈最底部移除。我自己認爲在with語句中,這時的執行環境就是對象b,而不是函數,所以首先訪問b中的a值。
    我嘗試在函數外直接訪問a,結果當然是undefined,因爲這時的執行環境應該是全局環境,而全局環境並沒有這個a值,只有通過b.a纔可以訪問b中的a,所以可以這樣說with語句其實還提供了簡寫訪問對象字段的途徑。假設b中有50個字段,你要全部訪問,正常情況你要寫50個b.xxx,而使用with語句只要直接寫字段名就行了。
    然而,我又有了一個疑問,我在with語句中創建一個變量,這個變量究竟屬於誰。如果按照我的理解,這個變量應該屬於對象b。

var b = {a:2};

function sayA(obj){
    var a = 1;
    with(b){a=5;c = 6;}
    alert(c);
}

sayA();
alert(b.c);
alert(b.a);

    但是, 運行結果是6、undefined和5。這說明with語句中的對象並不是作爲執行環境添加到作用域鏈中的,僅僅是作爲一個變量添加到with語句所在的執行環境之中,with語句中的變量還是屬於with語句所在的執行環境(這裏是函數sayA),而對b的字段的改變也會真正影響到b。

總結

    在with語句塊中,只是改變了對變量的遍歷順序,由原本的從執行環境開始變爲從with語句的對象開始。當嘗試在with語句塊中修改變量時,會搜索with語句的對象是否有該變量,有就改變對象的值,沒有就創建,但是創建的變量依然屬於with語句塊所在的執行環境,並不屬於with對象。
    離開with語句塊後,遍歷順序就會再次變成從執行環境開始。
    其實概括來說,和書本所總結的是一致的,with語句接收的對象會添加到作用域鏈的前端並在代碼執行完之後移除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章