咱們都知道變量對象會保存執行上下文中的一些數據,例如function declarations、formal parameters、variable、arguments,這些數據都會成爲變量對象的屬性。數組
當一進入執行上下文的時候,變量對象會進行初始化,在代碼執行的階段變量對象中的一些數據也會進行更新。bash
一樣與執行上下文密切相關還有做用域鏈,本篇文章將會介紹執行上下文中的做用域鏈。ide
做用域鏈與執行上下文密切相關,一系列變量對象組成的鏈經常使用於在標識符解析時查找變量。 函數
讓咱們先來舉一個簡單的例子:ui
var x = 10;
function Foo() {
var y = 20;
function bar() {
console.log(x + y);
}
return bar;
}
Foo()(); //30
複製代碼
咱們都知道沒進入一個執行上下文,就會有一個與該上下文密切相關的變量對象。對於全局上下文(global context)來講,其變量對象(variable object)就是全局對象(global object)。對於函數上下文來講就是活動對象(activation object),也稱爲變量對象。this
對於內部上下文來講,其做用域鏈(Scope Chain)是由全部父級的變量對象和自身的變量對象組成的。這條鏈經常使用於變量的查找。在上面這個例子中函數bar上下文的做用域鏈包括bar的活動對象、Foo的變量對象、全局變量對象。spa
當函數調用時,該函數上下文中的做用域鏈就會被建立。而且是由該函數上下文中的活動對象和函數的內部屬性[[scope]]所組成的。 就像下面這樣:code
activeExecutionContext = {
VO: {...}, // or AO
this: thisValue,
Scope: [ // Scope chain
// list of all variable objects
// for identifiers lookup
]
};
複製代碼
其做用域就是下面這樣:orm
Scope = AO + [[scope]]
複製代碼
經常將做用域鏈放在一個棧中,例如用js中的數組來模擬棧能夠表示成下面這個樣子:對象
var Scope = [vo1,vo2,vo3,...] //scope chain
複製代碼
固然你也能夠用對象來表示,經過引用父級做用域表示成分層對象鏈,用__parent__屬性來指向外部上下文中的變量對象。 例如:
var VO1 = {__parent__: VO2, ... other data}; -->
var VO2 = {__parent__: VO3, ... other data}; -->
// etc.
複製代碼
以上這種Scope = AO + [[scope]]的標識符解析過程,與函數的生命週期有關。將會在下面繼續討論