一个执行的上下文可以抽象的理解为object。每一个执行的上下文都有一系列的属性(我们称为上下文状态),他们用来追踪关联代码的执行进度。这个图示就是一个context的结构。

上下文结构
除了这3个所需要的属性(变量对象(variable object),this指针(this value),作用域链(scope chain) ),执行上下文根据具体实现还可以具有任意额外属性。接着,让我们仔细来看看这三个属性。
变量对象(Variable Object)
A variable object is a scope of data related with the execution context.
It’s a special object associated with the context and which stores variables and function declarations are being defined within the context.变量对象(variable object) 是与执行上下文相关的 数据作用域(scope of data) 。
它是与上下文关联的特殊对象,用于存储被定义在上下文中的 变量(variables) 和 函数声明(function declarations) 。
变量对象(Variable Object)是一个抽象的概念,不同的上下文中,它表示使用不同的object。例如,在global全局上下文中,变量对象也是全局对象自身[global object]。(这就是我们可以通过全局对象的属性来指向全局变量)。
让我们看看下面例子中的全局执行上下文情况:
var foo = 10; function bar() {} // // 函数声明 (function baz() {}); // 函数表达式 console.log( this.foo == foo, // true window.bar == bar // true ); console.log(baz); // 引用错误,baz没有被定义
全局上下文中的变量对象(VO)会有如下属性:

全局变量对象
如上所示,函数“baz”如果作为函数表达式则不被不被包含于变量对象。这就是在函数外部尝试访问产生引用错误(ReferenceError) 的原因。请注意,ECMAScript和其他语言相比(比如C/C++),仅有函数能够创建新的作用域。在函数内部定义的变量与内部函数,在外部非直接可见并且不污染全局对象。使用 eval 的时候,我们同样会使用一个新的(eval创建)执行上下文。eval会使用全局变量对象或调用者的变量对象(eval的调用来源)。
那函数以及自身的变量对象又是怎样的呢?在一个函数上下文中,变量对象被表示为活动对象(activation object)。
活动对象(activation object)
当函数被调用者激活,这个特殊的活动对象(activation object) 就被创建了。它包含普通参数(formal parameters) 与特殊参数(arguments)对象(具有索引属性的参数映射表)。活动对象在函数上下文中作为变量对象使用。
即:函数的变量对象保持不变,但除去存储变量与函数声明之外,还包含以及特殊对象arguments 。考虑下面的情况:
function foo(x, y) { var z = 30; function bar() {} // 函数声明 (function baz() {}); // 函数表达式 } foo(10, 20);
“foo”函数上下文的下一个激活对象(AO)如下图所示:

激活对象
同样道理,function expression不在AO的行列。
我们接下去要讲到的是第三个主要对象。众所周知,在ECMAScript中,我们会用到内部函数[inner functions],在这些内部函数中,我们可能会引用它的父函数变量,或者全局的变量。我们把这些变量对象成为上下文作用域对象[scope object of the context]. 类似于上面讨论的原型链[prototype chain],我们在这里称为作用域链[scope chain]。
延伸阅读
此文章所在专题列表如下:
- 我们应该如何去了解JavaScript引擎的工作原理
- JavaScript探秘:编写可维护的代码的重要性
- JavaScript探秘:谨慎使用全局变量
- JavaScript探秘:var预解析与副作用
- JavaScript探秘:for循环(for Loops)
- JavaScript探秘:for-in循环(for-in Loops)
- JavaScript探秘:Prototypes强大过头了
- JavaScript探秘:eval()是“魔鬼”
- JavaScript探秘:用parseInt()进行数值转换
- JavaScript探秘:基本编码规范
- JavaScript探秘:函数声明与函数表达式
- JavaScript探秘:命名函数表达式
- JavaScript探秘:调试器中的函数名
- JavaScript探秘:JScript的Bug
- JavaScript探秘:JScript的内存管理
- JavaScript探秘:SpiderMonkey的怪癖
- JavaScript探秘:命名函数表达式替代方案
- JavaScript探秘:对象Object
- JavaScript探秘:原型链 Prototype chain
- JavaScript探秘:构造函数 Constructor
- JavaScript探秘:可执行的上下文堆栈
- 执行上下文其一:变量对象与活动对象
- 执行上下文其二:作用域链 Scope Chains
- 执行上下文其三:闭包 Closures
- 执行上下文其四:This指针
- JavaScript探秘:强大的原型和原型链
- JavaScript函数其一:函数声明
- JavaScript函数其二:函数表达式
- JavaScript函数其三:分组中的函数表达式
- JavaScript函数其四:函数构造器
- JavaScript变量对象其一:VO的声明
- JavaScript变量对象其二:VO在不同的执行上下文中
- JavaScript变量对象其三:执行上下文的两个阶段
- JavaScript变量对象其四:关于变量
- JavaScript变量对象其五:__parent__ 属性
- JavaScript作用域链其一:作用域链定义
- JavaScript作用域链其二:函数的生命周期
- JavaScript作用域链其三:作用域链特征
- JavaScript闭包其一:闭包概论
- JavaScript闭包其二:闭包的实现
- JavaScript闭包其三:闭包的用法
本文地址:http://www.nowamagic.net/librarys/veda/detail/1644,欢迎访问原出处。
大家都在看