词法作用域(遮蔽效应,欺骗词法)

本文探讨了JavaScript中的词法作用域,详细解释了遮蔽效应,即当内部作用域中存在同名变量时对外部变量的隐藏。此外,还分析了全局变量与window对象的关系,以及如何通过window属性访问被遮蔽的全局变量。函数的词法作用域由声明位置决定,不受调用位置影响。eval()函数和with语句可以动态修改词法作用域,但在严格模式下eval有独立作用域,with则被禁止,因为它们会破坏性能优化。建议避免使用eval和with以维持代码的清晰和性能。

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

1 词法化

大部分标准表一起的第一个工作阶段是词法化,对源代码的字符进行检查,如果是有状态的解析过程还会赋予单词语义;

一般来说词法作用域是由书写代码时,把变量和块作用域写在哪里决定的,因此词法分析器在处理代码时会保持作用域不变(大部分情况是这样,而且我们推荐这样写);

2 遮蔽效应

作用域查找时,会在找到第一个匹配的标识符时停止,这叫做遮蔽效应;

全局变量会自动的成为全局对象(比如浏览器中的window对象)的属性,,因此不直接使用词法名称而是通过属性,比如window.a,就可以访问到被遮蔽的属性,但是如果是非全局变量被遮蔽了是无法访问的;

无论函数在哪里被调用以及如何调用,它的词法作用域都是由声明的位置决定;

3 欺骗词法

3.1 eval

JavaScript中的eval()函数可以接受一个字符串作为参数,其中的内容视为书写时就存在于此的代码;因此执行到eval()时,这段代码会动态插进来,并对词法作用域的环境进行修改;

严格模式下,eval()运行时有自己的词法作用域,也就无法修改所在的作用域;

3.2 with

with通常作为重复引用一个对象的多个属性的快捷方式,比如:

var obj={
  a:1,
  b:2
}
with(obj){
  a=3;
  b=5;//可以像使用词法变量一样使用
}

事实上with会把一个对象处理为一个完全隔离的词法作用域,因此如果写了


with(obj){ a=3; b=5; c=6}//会导致声明一个全局变量c,赋值为6,因为这里是LHS查找

严格模式下不允许使用with;

3.3性能

欺骗词法最大的问题在于会让js引擎失去它在编译阶段进行的性能优化,部分优化基于能够依赖词法的静态分析,预先确定所有变量和函数的定义位置,才能在执行时快速找到;但是使用了eval或with,js引擎只能假设关于标识符位置的判断都是无效的,因为不知道eval会接受什么代码,也不知道with创建的新作用域的内容使什么;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值