一段简单的JavaScript代码思考
先看一段简单的代码,打印结果是??为什么why??
从上述打印结果不难看出,在打印基本变量num、函数表达式fn、函数声明fun时,就已经知道变量num、函数表达式fn值为undefined,函数声明fun值为function
但这样会存在一个疑问?js在代码执行之前打印时(变量、函数表达式、函数声明)就存在值,那么在打印(变量、函数表达式、函数声明)之前究竟发了什么??
【答案是变量对象、执行上下文代码的2个阶段】
(当然 打印在基本变量num、函数表达式fn、函数声明fun之后结果是不言自明的)
变量对象 variable object
如果变量与执行上下文相关,那么它自己应该知道它的数据存储在哪里和如何访问。这种机制被称作 变量对象(variable object).
一个变量对象完全有可能用正常的ECMAScript对象的形式来表现
VO = {};
VO就是执行上下文的属性(property)
activeExecutionContext = { VO: { // context data (var, FD, function arguments) arguments 函数的所有形式参数 FunctionDeclaration 函数的声明 variable Declaration 变量声明 } };
处理上下文代码的2个阶段
- 进入执行上下文(代码执行之前时)
- 执行代码
变量对象的修改变化与这两个阶段紧密相关
(个人理解标注 变量对象与执行上下文关系强调是代码执行前后过程中变量对象的变化)
为了更好的理解执行上下文分阶段处理(包括进入执行上下文、执行代码)我们来看下下面test函数执行上下文分阶段处理过程
var a = 10; function test(x) { var b = 20; }; test(30);
在上述代码第5行代码,调用test激活函数至第3行代码之前时(包括第3行) x 值为 30, b值undefined
其对应变量对象简单表示如下
// Variable object of the global context VO(globalContext) = { a: 10, test: }; // Variable object of the "test" function context VO(test functionContext) = { x: 30, b:undefined };
执行test函数第3行代码后,函数test未弹出栈时,其对应的变量对象如下
// Variable object of the global context VO(globalContext) = { a: 10, test: }; // Variable object of the "test" function context VO(test functionContext) = { x: 30, b: 20 };
由于在函数执行上下文中,VO是不能直接访问的,此时由激活对象(activation object,缩写为AO)扮演VO的角色。
(标注 这里激活可以理解调用函数, 现实中更形象例子向水中投入石子,一石激起千层浪)
VO(functionContext) === AO;
且 执行上下文的属性(property)
activeExecutionContext = { VO: {} }
于是上述函数执行上下文中变量对象表示代码修改成如下形式
// Variable object of the global context activeExecutionContext = { // Variable object of the global context AO(globalContext) = { a: 10, test: }; // Variable object of the "test" function context VO(test functionContext) = { x: 30, b: 20 }; }
变量对象VO(variable object)就是执行上下文的属性(property)
变量对象中的变量在执行上下文中默认次序变量声明在顺序上跟在函数声明和形式参数声明之后
activeExecutionContext = { VO: { // context data (var, FD, function arguments) arguments 函数的所有形式参数(如果我们是在函数执行上下文中) (变量对象的一个属性,这个属性由一个形式参数的名称和值组成;如果没有对应传递实际参数,那么这个属性就由形式参数的名称和undefined值组成) FD 所有函数声明(FunctionDeclaration, FD)变量对象的一个属性,这个属性由一个函数对象(function-object)的名称和值组成;如果变量对象已经存在相同名称的属性,则完全替换这个属性。 VD 所有变量声明(var, VariableDeclaration) 变量对象的一个属性,这个属性由变量名称和undefined值组成;如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。 } };
代码体现
alert(x); // function var x = 10; alert(x); // 10 x = 20; function x() {}; alert(x); // 20
Tom大叔 深入理解JavaScript系列(12):变量对象(Variable Object)
英文地址 : ECMA-262-3 in detail.Chapter 2.Variable object
中文地址 : [JavaScript]ECMA-262-3 深入解析.第二章.变量对象