ECMAScript VO and AO
变量对象 (缩写为VO)就是与执行上下文相关的对象,它存储下列内容:
1. 变量 (var, VariableDeclaration);
2. 函数声明 (FunctionDeclaration, 缩写为FD);
3. 函数的形参
VO就是执行上下文的属性之一(property)
只有全局上下文的变量对象允许通过VO的属性名称间接访问(因为在全局上下文里,全局对象自身就是一个VO(稍后会详细介绍)。在其它上下文中是不可能直接访问到VO的,因为变量对象完全是实现机制内部的事情。当我们声明一个变量或一个函数的时候,同时还用变量的名称和值,在VO里创建了一个新的属性。
对于所有类型的执行上下文来说,变量对象的一些操作(如变量初始化)和行为都是共通的。从这个角度来看,把变量对象作为抽象的基本事物来理解更容易。而在函数上下文里同样可以通过变量对象定义一些相关的额外细节:
在函数执行上下文中,VO是不能直接访问的,此时由激活对象(Activation Object,缩写为AO)扮演VO的角色。激活对象 是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性的值是arguments object。
Arguments Objects 是函数上下文里的激活对象AO中的内部对象,它包括下列属性:
1. callee — 指向当前函数的引用;
2. length — 真正传递的参数的个数;
3. properties-indexes (字符串类型的整数) 属性的值就是函数的参数值(按参数列表从左到右排列)。 properties-indexes内部元素的个数等于arguments.length. properties-indexes 的值和实际传递进来的参数之间是共享的。(译者注:共享与不共享的区别可以对比理解为引用传递与值传递的区别)
原理:
执行上下文的代码被分成两个基本的阶段来处理:
l 进入执行上下文;
l 执行代码;
(变量对象的变化与这两个阶段紧密相关)
当进入执行上下文(代码执行之前)时,VO已被下列属性填充满(这些都已经在前文描述过)
1. 函数的所有形式参数(如果我们是在函数执行上下文中)
2. 所有函数声明(FunctionDeclaration, FD)
3. 所有变量声明(var, VariableDeclaration)
函数表达式(FunctionExpression, 缩写为 FE) 而不是函数声明不会影响VO
当AO/VO 已经被属性(并不是所有的属性都有值,大部分属性的值还是系统默认的初始值undefined )填满
“不管是使用var关键字(在全局上下文)还是不使用var关键字(在任何地方),都可以声明一个变量”。请记住,这绝对是谣传:任何时候,变量只能通过使用var关键字才能声明。
关于变量,还有一个重要的知识点。变量相对于简单属性来说,变量有一个特性(attribute):{DontDelete},这个特性的含义就是不同通过delete操作符直接删除变量属性。
前面已经提到过,按标准规范,激活对象是不可能被直接访问到的。但是,一些具体实现并没有完全遵守这个规定,例如SpiderMonkey和Rhino;在这些具体实现中,函数有一个特殊的属性 __parent__,通过这个属性可以直接引用到函数已经创建的激活对象或全局变量对象。
在上面的例子中我们可以看到,函数foo是在全局上下文中创建的,所以属性__parent__ 指向全局上下文的变量对象,即全局对象。
ECMA英文原文地址:http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/
参考中文呢地址:http://www.cnblogs.com/justinw/archive/2010/04/23/1718733.html