導言
在第二章關于變量對象的描述中,我們已經知道一個執行上下文 (變量、函數聲明和函數的形參)的數據作為屬性存儲在變量對象中。
同時我們也知道變量對象在每次進入上下文時創建,并填入初始值,值得更新出現在代碼執行階段。
這一章專門討論與執行上下文直接相關的更多細節,這次我們將提及一個議題——作用域鏈。
定義
如果要簡要的描述并展示其重點,作用域鏈大多數與內部函數相關。
我們知道,ECMAScript 允許創建內部函數,我們甚至能從內部函數中返回這些函數。
var x = 10;function foo() { var y = 20; function bar() { alert(x + y); } return bar;}foo()(); // 30
這樣,很明顯每個上下文擁有自己的變量對象 ,對于全局上下文,它是全局對象自身,對于函數,它是激活對象。
作用域鏈完全是內部上下文所有變量對象(包括父變量對象)的列表。此鏈用來變量查詢。即在上面的例子中,“bar”上下文的作用域鏈包括AO(bar)、AO(foo)和VO(global)。
但是,讓我們仔細研究這個問題。
讓我們從定義開始,并進深一步的討論例子。
作用域鏈與一個執行上下文相關,變量對象的一條鏈在標識符解析中用于變量查找。
一個函數上下文的作用域鏈在函數調用時創建包含激活對象和這個函數內部的[[scope]]屬性。下面我們將更詳細的討論一個函數的[[scope]]屬性。
在上下文中示意如下:
activeExecutionContext = { VO: {...}, // or AO this: thisValue, Scope: [ // Scope chain // list of all variable objects // for identifiers lookup ]};
這里scope定義如下:
Scope = AO + [[Scope]]
這種聯合和標識符解析過程,我們將在下面討論,這與函數的生命周期相關。