前面的文章說到, 執行上下文的建立階段,主要有三個內容:javascript
一、建立變量對象;二、初始化做用域鏈;三、肯定this的指向。java
執行上下文的執行階段,也有三個內容:git
一、變量賦值;二、函數引用;三、執行其餘代碼。github
在這裏先說一個前提,我提到的函數調用,說的是執行上下文的第一階段,建立階段(還沒開始執行函數體相關的代碼),提到的函數執行,說的是執行上下文的第二階段,執行階段(開始執行函數體相關的代碼)。瀏覽器
其實在說到執行上下文中的的變量對象的時候,我印象中會冒出來兩個英文簡寫:VO和AO。函數
VO:Variable Object的簡寫,就是變量對象。this
AO:Activation Object的簡寫,叫作活動對象。code
這兩個東西有什麼區別呢?對象
個人理解是,他們的區別就是在於執行上下文的不一樣生命週期階段,變量對象VO在執行上下文的建立階段,而活動對象AO在執行上下文的執行階段。生命週期
先說一下變量對象,它的結構大體如此,在函數被調用的時候被建立:
VO:{ arguments:Arguments, FunctionName:reference to function FunctionName(){}, Variables:undefined }
VO(變量對象)包含:函數的形參(arguments)、函數聲明(FunctionDeclaration, FD)、變量聲明(VariableDeclaration,var)三個內容。
簡單來講,舉個例子:
//聲明example函數 function example(x){ var a = 10; function plus(){ return a + x; } return plus(); } //調用example函數 example(5);
當調用example函數的時候,進入執行上下文的建立階段,建立的變量對象爲(本身看看什麼是函數的形參、函數聲明和變量聲明):
VO:{ arguments:{x:undefined}, plus:reference to function plus(){}, a:undefined }
當example函數開始執行的時候,進入執行上下文的執行階段,變量對象就會被激活,首先經過arguments屬性初始化成爲活動對象AO:
AO:{ arguments:{callee:example,x:5,length:1}, plus:reference to function plus(){}, a:undefined }
固然了,arguments屬性的值是Arguments對象,對於VO來講,因爲建立階段只是形參,因此VO只有x一個undefined的值,而經過傳入肯定的實參5初始化後,AO中的Arguments就多了指向自身函數callee和length兩個屬性了。
固然,AO對象是隨着執行代碼的執行過程當中而變化的,隨着代碼的執行,變量開始初始化,下一步AO就會變成:
AO:{ arguments:{callee:example,x:5,length:1}, plus:reference to function plus(){}, a:10 }
當還有其餘變量的時候,執行過程自行理解一下就好了。
因此上下文的執行階段:變量賦值、函數引用、執行其餘代碼。這個過程也能夠輕易理解了。
最後,想說一下全局上下文(或者叫作全局執行上下文)的VO和AO,其實你們也能夠知道,其實咱們執行全部的代碼,都是基於一個全局上下文上的,只要你不退出全局上下文(例如瀏覽器的話全局對象就是window,你不關閉窗口的話,全局上下文就不會跳出執行上下文棧),就一直都在全局執行上下文的執行階段了,因此執行的階段就已是AO了。其次,自己沒有arguments屬性,這個也能夠容易理解,全局對象它不是函數。