深入理解JavaScript系列(12) 變量對象(Variable Object)
2024-05-06 14:22:37
供稿:網友
JavaScript編程的時候總避免不了聲明函數和變量,以成功構建我們的系統,但是解釋器是如何并且在什么地方去查找這些函數和變量呢?我們引用這些對象的時候究竟發生了什么?
原始發布:Dmitry A. Soshnikov
發布時間:2009-06-27
俄文地址:http://dmitrysoshnikov.com/ecmascript/ru-chapter-2-variable-object/
英文翻譯:Dmitry A. Soshnikov
發布時間:2010-03-15
英文地址:http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/
部分難以翻譯的句子參考了justinw的中文翻譯
大多數ECMAScript程序員應該都知道變量與執行上下文有密切關系:
代碼如下:
var a = 10; // 全局上下文中的變量
(function () {
var b = 20; // function上下文中的局部變量
})();
alert(a); // 10
alert(b); // 全局變量 "b" 沒有聲明
并且,很多程序員也都知道,當前ECMAScript規范指出獨立作用域只能通過“函數(function)”代碼類型的執行上下文創建。也就是說,相對于C/C++來說,ECMAScript里的for循環并不能創建一個局部的上下文。
代碼如下:
for (var k in {a: 1, b: 2}) {
alert(k);
}
alert(k); // 盡管循環已經結束但變量k依然在當前作用域
我們來看看一下,我們聲明數據的時候到底都發現了什么細節。
數據聲明
如果變量與執行上下文相關,那變量自己應該知道它的數據存儲在哪里,并且知道如何訪問。這種機制稱為變量對象(variable object)。
變量對象(縮寫為VO)是一個與執行上下文相關的特殊對象,它存儲著在上下文中聲明的以下內容:
變量 (var, 變量聲明);
函數聲明 (FunctionDeclaration, 縮寫為FD);
函數的形參
舉例來說,我們可以用普通的ECMAScript對象來表示一個變量對象:
代碼如下:
VO = {};
就像我們所說的, VO就是執行上下文的屬性(property):
activeExecutionContext = {
VO: {
// 上下文數據(var, FD, function arguments)
}
};
只有全局上下文的變量對象允許通過VO的屬性名稱來間接訪問(因為在全局上下文里,全局對象自身就是變量對象,稍后會詳細介紹),在其它上下文中是不能直接訪問VO對象的,因為它只是內部機制的一個實現。
當我們聲明一個變量或一個函數的時候,和我們創建VO新屬性的時候一樣沒有別的區別(即:有名稱以及對應的值)。
例如:
代碼如下:
var a = 10;
function test(x) {
var b = 20;
};
test(30);
對應的變量對象是:
代碼如下:
// 全局上下文的變量對象
VO(globalContext) = {
a: 10,
test: <reference to function>
};
// test函數上下文的變量對象
VO(test functionContext) = {
x: 30,
b: 20
};
在具體實現層面(以及規范中)變量對象只是一個抽象概念。(從本質上說,在具體執行上下文中,VO名稱是不一樣的,并且初始結構也不一樣。