上一篇我們講了作用域,也留了一個問題,我們是真的在作用域裏取到變量的值嗎?
在上一篇裏也給出了答案,我們不是在作用域裏取到變量的值,而是在作用域所對應的執行上下文取到變量的值,並且可能同樣的作用域,相同的變量取到的值是不同的。
在這裏,提一句很重要的話,作用域在函數創建的時就已經確定了,而不是在函數調用時確定。
下面我們將按照程序執行的順序,一步一步把各個上下文環境加上。
第一步,在加載程序時,已經確定了全局上下文環境,並隨着程序的執行而對變量就行賦值,
在這裏提一句,函數的執行上下文是在調用函數後建立的,執行上下文的第一階段(準備階段)是在調用函數後,執行具體代碼前進行,執行上下文的第二階段(執行階段)是執行具體代碼時進行的。
第二步,程序執行到第27行,調用fn(10),此時生成此次調用fn函數時的上下文環境,壓棧,並將此上下文環境設置爲活動狀態
第三步,執行到第23行時,調用bar(100),生成此次調用的上下文環境,壓棧,並設置爲活動狀態
第四步,執行完第23行,bar(100)調用完成。則bar(100)上下文環境被銷燬。接着執行第24行,調用bar(200),則又生成bar(200)的上下文環境,壓棧,設置爲活動狀態。
第五步,執行完第24行,則bar(200)調用結束,其上下文環境被銷燬。此時會回到fn(10)上下文環境,變爲活動狀態
第六步,執行完第27行代碼,fn(10)執行完成之後,fn(10)上下文環境被銷燬,全局上下文環境又回到活動狀態
所有過程到此結束。
我們可以看出,作用域只是一個“區域”,一個抽象的概念,其中沒有變量。要通過作用域對應的執行上下文環境來獲取變量的值。同一個作用域下,不同的調用會產生不同的執行上下文環境,繼而產生不同的變量的值。
所以,如果要查找一個作用域下某個變量的值,就需要找到這個作用域對應的執行上下文環境,再在其中尋找變量的值。
如果想檢驗自己對以上的概念是否掌握清楚,可以試一下下面的例子,如果能理解其結果,那麼說明你已經掌握了。
function a(){
var age=21;
var height=178;
var weight=70;
function b(){
alert(age);//undefined
alert(height);//178
var age=25;
height=180; //不帶var的聲明,不管這個變量在哪個位置,都相當於是在全局作用域裏聲明瞭height變量。
alert(age);//25
alert(height); //180
}
b();
}
a();
這裏需要把這一篇連同前三篇的內容都看懂才能理解上面例子的結果。如果有疑問,我會在下一篇拿一整個篇幅講一下我的理解。
下一篇: javascript執行上下文、作用域與閉包(第五篇)—一個例子的理解
本文參考了王福朋老師的深入理解javascript原型和閉包(13)