javascript執行上下文、作用域與閉包(第五篇)---一個例子的理解

在上一篇裏,留下了一個例子,如果對那個例子不是太懂,沒關係,我會在這一篇裏詳細講一下我對這個例子的理解。

下面是這個例子:

function a(){
var age=21;
var height=178;
var weight=70;
function b(){
    alert(age);//undefined
    alert(height);//178
    var age=25;
    height=180;   //相當於是在全局作用域裏聲明瞭height變量。
    alert(age);//25
    alert(height); //180 
     }

      b();
}

a(); //備註:如果在函數作用域內聲明變量不加var,相當於是在全局作用域裏聲明瞭這個變量。

爲了更好的理解,我們變一下這個代碼,


 var height;

function a(){

  var age=21;
  var height=178;
  var weight=70;
  function b(){

     alert(age); //undefined
     alert(height); //178
     var age=25;
     height=180;   
     alert(age); //25
     alert(height); //180

     }

  a();

我們來一步一步的理解這個例子:

第一步,在加載程序時,已經確定了全局上下文環境,並隨着程序的執行而對變量就行賦值;
這裏寫圖片描述

第二步,程序執行到第31行,調用a(),此時生成此次調用a()函數時的上下文環境,壓棧,並將此上下文環境設置爲活動狀態
這裏寫圖片描述

第三步,執行到第28行時,調用b(),生成此次調用的上下文環境,壓棧,並設置爲活動狀態
這裏寫圖片描述

(可不要忘了執行上下文的兩個階段,一個是創建階段,一個是執行階段,如果忘記了,趕緊翻一下我之前的文章喲)

到此,我們可以理解爲什麼第一個alert(age)的結果是undefined,從b()創建階段時的上下文可知,age:undefined . 爲什麼語句height=180 沒有在b()創建階段時的上下文生成height:undefined?因爲此時height=180是賦值語句,不是變量的聲明語句。只有變量的聲明語句纔會在b()創建階段時的上下文中生存相應的屬性。

爲什麼第二個alert(height)的結果是178呢?這時候就要聯繫到作用域鏈的知識了,因爲在b()的作用域所對應的執行上下文裏沒找到height的屬性,所以從創建函數b()的作用域所對應的執行上下文裏找相關屬性,也就是a()的執行上下文,在a()的執行上下文裏找到了height屬性,它的屬性值爲178.

爲什麼第三個alert(age)的結果是25呢?這個就很好理解了吧,在b()執行階段的上下文裏,會完成對變量的賦值, 所以age賦值爲25.

爲什麼第四個alert(height)的結果是180呢?因爲height=180是個賦值語句,所以它就會找到height的屬性,把它賦值爲180,沿着作用域鏈,它在a()的上下文找到了height屬性,並把它賦值爲180,覆蓋掉原來的屬性值178.

如果理解了這個例子,是不是對執行上下文,作用域鏈的理解更深刻了呢。

我們在第一篇就講到,閉包和執行上下文,作用域聯繫緊密,下一篇就來講一講在js中那個“深奧”的閉包。


下一篇: javascript執行上下文、作用域與閉包(第六篇)—閉包

如果還沒懂的趕緊看一遍我之前的文章,並且一定要看懂噢。

javascript執行上下文、作用域與閉包(第一篇)—執行上下文
javascript執行上下文、作用域與閉包(第二篇)—作用域
javascript執行上下文、作用域與閉包(第三篇)—自由變量與作用域鏈
javascript執行上下文、作用域與閉包(第四篇)—作用域與執行上下文

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