当上下文控制权在某个执行上下文时,变量对象就会变成活动对象。
两者的区别是
1、变量对象(VO)是规范上或者是JS引擎上实现的,并不能在JS环境中直接访问。
2、当进入到一个执行上下文后,这个变量对象才会被激活,所以叫活动对象(AO),这时候活动对象上的各种属性才能被访问。
变量对象的创建
1、 Chrome 浏览器中,变量对象会首先获得函数的参数变量及其值;在 Firefox 浏览器中,是直接将参数对象 arguments 保存在变量对象中。
2、在变量对象中添加函数名为key 函数所在内存地址的引用为value,如果相同函数名则覆盖。
3、获取变量名为key,undefined为value,遇到同名的函数名或者同名的变量名则跳过,不进行覆盖。此处为var声明的变量,let和const声明是执行阶段才开始执行。
全局上下文的变量对象
windowEC = {
VO:window
}
变量对象 相关例子1
var a = 20;
var b = 30;
function fn() {console.log('fn')} ;
function fn() {console.log('cover fn.')};
function a() {console.log('cover a.')};
console.log(a);
console.log(b);
fn();
var fn = 'I wa cover function named fn.';
console.log (fn);
创建阶段
函数优先
fn
fn(覆盖上一个fn)
a
变量
a(跳过)
b
fn(跳过)
VO = {
arguments:{},
fn:<fn reference>,
a:<a reference>,
b:undefined
}
执行阶段
AO = {
arguments:{},
fn:'I wa cover function named fn.',
a:20,
b:30
}
输出的值是:
20
30
cover fn.
I wa cover function named fn.
变量对象 相关例子2
函数 bar 的变量对象中是否包含了变量a?
function foo () {
var a = 20;
function bar() {
a = 30; // 我猜没有 这里改的应该是foo的变量对象里面的a变量
console.log(a);
}
bar() ;
console.log(a);// 这里a也被改变了
}
foo();
30
30
变量对象 相关例子3
函数执行上下文带参数的话,在创建阶段就会被赋值。
function foo(a) {
var b = 2;
function c() {}
var d = function() {};
b = 3;
}
foo(1);
AO(foo) = {
arguments: {
0: 1,
length: 1
},
a: 1,
b: undefined,
c: <c reference>,
d: undefined
}
变量提升
console.log(a);
var a = 30;
相当于
var a = undefined;
console.log(a);
a = 30;
通过var定义的变量,会在变量对象创建阶段给变量a赋值undefined,在console.log(a)的时候就不会报错,我们叫做变量提升。
函数提升
foo();
function foo() {
console.log('foo');
}
相当于
function foo() {
console.log('foo');
}
foo();
在变量对象创建的时候,foo已经指向,不像变量会被赋值undefined,在执行foo()的时候就不会报错,也能够正常的输出'foo',我们叫做函数提升。