关于JavaScript中的变量提升和使用未经声明的变量会产生全局变量的原因

本文探讨了JavaScript中变量提升的概念及其对作用域的影响。详细解释了编译器如何处理变量声明,以及引擎如何在运行时查找并赋值给变量。此外还介绍了LHS和RHS查询的区别及它们在变量查找中的作用。

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

1 js编译过程,理解变量提升

包括 引擎、编译器和作用域;

以var a = 2; 为例,

编译器把代码分解为词法单元,把词法分解为一个树结构。

然后当编译器进行代码生成时,

1,对于var a ,编译器询问作用域是否已经有一个同名的变量存放在当前作用域;是则忽略该声明,否则要求作用域在当前作用于的集合中声明一个新的变量,命名为a;

2,接下来编译器为引擎生成运行时需要的代码,这些代码用来处理a=2;引擎运行时首先询问作用域当前作用域是否存在变量a,是则使用它,否则继续查找;如果最终找到了,则赋值给a,如果没有,则抛出异常;

总结:变量的赋值操作:1),编译器在当前作用域声明一个变量(如果之前没有声明过);2),运行时引擎在作用域链里寻找该变量,如果找到了就赋值;

2 LHS和RHS查询,理解变量的声明和使用

引擎查找变量时,有LHS两种RHS查询,虽然RL是左右的缩写,但这里最好理解为查找“赋值操作的目标是谁LHS”“谁是赋值操作源头RHS”;(LHS是赋值操作用的,RHS则是找到它使用它的值);

例:

function foo(a){
  console.log(a);
}
foo(2);

引擎:foo>RHS

引擎:执行foo,a>LHS

引擎:console>RHS:

引擎:a>RHS

引擎:a的值传递给log()

那么,为什么要区分RHS和LHS,

因为在变量还没有声明的时候,这两种查询的行为是不同的;

RHS如果没找到,会抛出ReferenceError异常;LHS如果到了全局都没找到,则会创建一个全局变量交给他;这也是之所以函数内部使用未经声明的变量会成为全局变量的原因;

另外,在严格模式下,LHS没找到也会抛出ReferenceError异常;而使用RHS找到一个变量,使用不合理的操作时(比如引用null或者undefined的属性或者对一个非函数类型的值进行函数调用),则会抛出TypeError异常,这说明起码作用域判别成功了但是,操作时非法或者不合理的;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值