Javascript变量对象

JavaScript中的变量对象(Variable Object)存储所有变量和函数声明。它包括函数参数、函数声明和变量声明。创建过程在Chrome中是先获取参数,Firefox中直接保存arguments对象。函数声明优于变量声明,同名函数会覆盖变量。在执行阶段,变量赋值才真正完成,如`var a = 30`。这个过程被称为变量提升。全局上下文的变量对象是window,其生命周期与程序相同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Javascript变量对象
在JS代码中声明的所有变量都保存在变量对象(Variable Object)中,除此之外,变量对象种还包括以下内容:
1、函数的所有参数(Firefox中为参数对象arguments)
2、当前上下文中的所有函数声明(通过function声明的函数)
3、当前上下文的所有变量声明(通过var声明的变量)

  1. 创建过程
    在Chrome浏览器中变量对象首先获得函数的参数变量及其值;在Firefox浏览器中,是直接将参数对象arguments保存在变量对象中。
    依次获取当前上下文的所有函数声明,也就是使用function关键字声明的函数。在变量对象中会以函数名建立一个属性,属性值为指向该函数所在的内存地址引用。如果函数名的属性已经存在,那么该属性的值会被新的引用覆盖。
    依次获取当前上下文中的变量声明,也就是使用var关键字声明的变量。每找到一个变量声明,就在变量对象中就以变量名建立一个属性,属性值为undefined,则会直接跳过,原属性值不会被修改。
    ES6支持新的变量声明方式let/const,规则与var 完全不同,它们是在上下文的执行阶段开始执行的,避免了变量提升带来的一系列问题,
    具体执行过程:

    var a = 30;

    首先执行上下文的创建阶段会先确认变量对象,而变量对象的创建过程则是先获取变量名并赋值为undefined,因此第一步是:

    var a= undefined;

上下文的创建阶段完毕后,开始进入执行阶段,在执行阶段需要完成变量赋值工作,因此第二步是:a = 30;
需要注意的是,这两步分别是在上下文的创建阶段和执行阶段完成的,因此var a= undefined 这一步是提前到了比较早的地方去执行,下面通过一个简单的例子来证明。

console.log(a);
var a =30;

undefined
//创建阶段
var a=undefined
//执行阶段
console.log(a);
a=30;
这种现象称之为变量提升。
可以看出,在变量对象的创建过程中,函数声明的执行优先级会比变量声明的优先级更高一点,而且同名的函数会覆盖函数与变量,但是同名的变量不会覆盖函数。
但是在上下文的执行阶段,同名的函数会被变量重新赋值。

var a=20;
function fn(){console.log('fn')};
function fn(){console.log('cover fn.')};
function a(){console.log('cover a.')};
console.log(a);
fn();
var fn = 'I want cover function namedcfn.';
console.log(fn);

创建阶段

function fn(){console.log('fn')};
function fn(){console.log('cover fn.')};
function a(){console.log('cover a.')};
var a= undefined;
var fn=undefined;

执行阶段

console.log(a);
fn();
var fn = 'I want cover function namedcfn.';
console.log(fn);
  1. 实例分析
function test(){
	conslole.log(a);
	console.log(foo());

    var a=1;
	function foo(){
		return 2;
    }
}
test();

运行test函数时,对应的上下文开始创建,可以用如下形式表达这个过程;
//创建过程

testEC={
	VO:{},    //变量对象
	scopeChain:[],  //作用域链
	this:{ }
}
	
VO={
	arguments:{...},
	foo:<foo reference>,
	a:undefined
}

在函数调用栈中,如果当前上下文处于函数调用栈的栈顶,则意味着当前上下文处于激活状态,此时变量对称为活动对象(AO ,Activation Object).活动对象中包含变量对象的所有属性;并且此时所有的属性都已经完成了赋值,除此之外,活动对象还包含了this的指向。

//执行阶段
vo->AO
AO={
arguments:{},
foo:<foo reference>,
a:1,
this:window
}

可以通过断点调式的方法在Chrome开发者中查看这一过程,
因此上面的例子实际执行顺序如下:

function test(){
	function foo(){
		return 2;
    }
    var a=undefined;
	conslole.log(a);
	console.log(foo());
	 a=1;
	
}
test();
  1. 全局上下文的变量对象
    以浏览器为例,全局对象为window对象
    全局上下文的变量对象有一个特殊的地方,即它的变量对象就是window对象,而且全局上下文的变量对象不能变成活动对象,
//以浏览器为例,全局对象为window
//全局上下文
windowEC={
	VO:window,
	scopeChain:{ },
	this:window
}

除此之外,全局上下文的生命周期与程序的生命周期一致,只要程序运行不结束(比如关掉浏览器窗口),全局上下文就会一直存在,其他所有的上下文环境都能直接访问全局上下文的属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值