導言
在程序中我們總要聲明變量和函數,然后成功的用它們來構建我們的系統。當我們引用需要的對象時,解釋器如何、在哪里找到我們的數據(functions,variable),會發生什么?
很多ECMAScript 程序員都清楚變量與執行上下文密切相關。
var a = 10; // variable of the global context(function () { var b = 20; // local variable of the function context})();alert(a); // 10alert(b); // "b" is not defined
同時,很多程序員也知道,在當前版本的規范中,獨立的作用域只能通過“function”代碼類型的執行上下文來創建。也就是說,對比C/C++,ECMAScript 中的循環塊不能創建一個局部的上下文。
for (var k in {a: 1, b: 2}) { alert(k);}alert(k); // variable "k" still in scope even the loop is finished
當聲明數據時會發生什么?讓我們看看更多細節。
數據聲明
當變量與執行上下文相關,它應該知道數據存儲在哪里,如何得到它。這種機制稱之為變量對象。
變量對象(縮寫為VO)是與執行上下文相關的對象,它存儲:
在上下文中聲明 |
例如,它可以表現為正常的ECMAScript對象的變量對象:
VO = {};
正如我們所說,VO是執行上下文的屬性:
activeExecutionContext = { VO: { // context data (var, FD, function arguments) }};
間接引用變量(通過VO的屬性名)只限于全局上下文的變量對象(在那里全局對象自身就是變量對象,稍后將涉及到)。對于其它作用域,直接引用一個VO是不可能的,它完全是執行機制。
當我們聲明一個變量或一個函數時,并沒有為VO創建一個新的屬性,該屬性擁有我們變量的名字和值。
例如:
var a = 10;function test(x) { var b = 20;};test(30);
相應的變量對象是:
// Variable object of the global contextVO(globalContext) = { a: 10, test:<reference to function>};// Variable object of the "test" function contextVO(test functionContext) = { x: 30, b: 20};
但是,在執行期間(和規范中),變量對象是一個抽象的實體。從根本來講,在具體的執行上下文中,VO命名不同,并且有不同的初始結構。