当函数执行时,会创建一个称为执行上下文的内部对象(可理解为作用域)。一个执行上下文定义了一个函数执行时的环境。
(1)在JavaScript解释器内部,每次调用执行上下文,分为两个阶段,①创建阶段 和 ②激活/代码执行阶段。
第一阶段是创建阶段,(当函数被调用,但未执行任何其内部代码之前)。在创建阶段主要做三件事:
(1)创建作用域链(Scope Chain)。 (2)创建变量对象(函数的形参、函数声明、变量声明)。 (3)求”this“的值。
当调用foo(22)时,创建状态如下所示
(1)创建状态负责处理定义属性的名字,不为其指派具体的值,以及形参/实参的处理。
(2)一旦创建阶段完成,执行流进入函数并且激活/代码执行阶段,Execution Context object就会更新。
(1)对于每个执行上下文(Execution Context)都有三个重要的属性,①变量对象(Variable object,VO),②作用域链(Scope chain)和 ③this。
(1)变量对象(variable object) 是与执行上下文相关的 数据作用域(scope of data) 。
(2)VO是与上下文关联的特殊对象,用于存储被定义在上下文中的 变量(variables) 和 函数声明(function declarations) 。
(3)VO是一个抽象的概念,不同的上下文中,它表示使用不同的object。例如,在global全局上下文中,变量对象也是全局对象自身[global object]。(这就是我们可以通过全局对象的属性来指向全局变量)。
进入执行上下文时,VO的初始化过程具体如下:
(1)函数的形参(当进入函数执行上下文时) 变量对象的一个属性,其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined。
(2)函数声明(FunctionDeclaration, FD) 变量对象的一个属性,其属性名和值都是函数对象创建出来的;如果变量对象已经包含了相同名字的属性,则替换它的值。
(3)变量声明(var,VariableDeclaration) 变量对象的一个属性,其属性名即为变量名,其值为undefined;如果变量名和已经声明的函数名或者函数的参数名相同,则不会影响已经存在的属性。
(1)只有全局上下文的变量对象允许通过VO的属性名称间接访问;
(2)在函数执行上下文中,VO是不能直接访问的,此时由激活对象(Activation Object,缩写为AO)扮演VO的角色。
(3)激活对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。
对于VO和AO的关系可以理解为,VO在不同的Execution Context中会有不同的表现:当在**Global Execution Context中,可以直接使用VO;但是,在函数Execution Context中,AO**就会被创建。
参考文章