一、JS的编译和传统的语言有何不同?
我们通常认为javascript是「动态的」、「解释性」的语言。但事实上,javascript是一门编译性语言。
传统的编译性语言,源代码执行之前,会经历三个步骤:
JS的引擎要做的事情,比这三个步骤复杂很多。
对于JS来说,编译的过程一般只在代码执行前的几微秒,甚至更短。
var a = 2 发生了什么?
在理解作用域前,我们介绍今天的三位主角
当JS遇到var a = 2
的时候,会发生下面这些事情。
一、当js遇到var a
的时候。编译器会先找作用域问一下,a
这个变量是否存在?
二、编译器为引擎
生成代码
生成的代码用来处理a = 2
.
当引擎运行这段代码时,引擎会去找作用域,当前作用域有没有a
变量?没有的话,上级作用域有吗?然后就会一直往上找。
如果找到a变量,就会对a变量进行赋值,如果没有找到,引擎就会抛出异常。
完整的流程大概是这样的:
LHS查询和RHS查询
- 当变量出现在赋值操作的左侧的时候,进行LHS查询
- 当变量出现在赋值操作的右侧的时候,进行RHS查询
其实这么说,并不准确。
更加容易理解的说法是这样的:
RHS 就是查找某个变量(或者是方法)
LHS 是视图查找变量的容器本身
,从而可以对这个变量容器
进行赋值。
这样说,还是有一点抽象。我们下面看一个例子,看看引擎和作用域是如何对话的。
function foo(a) {
console.log(a)
}
foo(2)
引擎:(第一次RHS查询)
作用域老大,我要为foo进行RHS引用,你见过吗?
作用域:
刚刚编译器声明了一个foo方法,给你。
引擎执行中...
引擎:(第一次LHS查询)
作用域老大,我要为a进行LHS引用,你见过吗?
作用域:
编译器把它声明成一个形参了,拿去吧
引擎执行中...把2赋值给a
引擎:(第二次RHS查询)
作用域老大,我要为console进行RHS引用
作用域:
它是一个内置对象,拿去
引擎执行中...查找到console下面还有一个log方法,继续执行
引擎:(第三次RHS查询)
作用域老大,我要为a进行RHS引用,你帮我看看它还在不在?
作用域:
放心,它没有发生变化,拿去用
引擎:
谢谢,我继续执行....
由此可见,上面的代码分别进行了三次RHS查询
和一次LHS查询
作用域嵌套
引擎
从当前作用域找,找不到会向父级
作用域查找,如果依然没有找到,会一直找到全局作用域。
如果找到顶层,无论是否找到,都会停止查找
举个例子:
function foo (a) {
console.log(a + b)
}
var b = 1;
foo(2)
引擎:(RHS查询)
foo作用域,我要为b进行RHS引用,你见过吗?
foo作用域:
啥玩意,没听说过,滚?!
引擎:(继续查找)
foo作用域的上级作用域兄弟,我要为b进行RHS引用,你见过吗?
全局作用域:
我见过b,编译器刚刚声明了一个b,拿走吧
为啥要区分LHS和RHS查询?
划重点:LHS和RHS查询,查询不到的变量的时候,结果是不一样的
- LHS查询,如果查询到全局作用域,都找不到变量,会很热心的
声明一个变量,并返还给引擎
- RHS查询,如果找不到变量,会
抛出异常ReferenceError
!
- RHS查询,找到变量,但是进行不合理的应用的时候,会
抛出异常TypeError
总结
1、作用域有一套自己的规则
。用于确定在什么地方、如何查找
变量。
2、如果查找的目的是赋值
,进行LHS查询
3、如果查找的目的是获取变量的值
,则进行RHS查询
4、LHS和RHS查询都会从当前作用域向上查找,如果找到则终止查询,如果找不到,一直找到顶层作用域。在顶层无论找到或者找不到,都终止查询。
5、不成功的RHS查询,会抛出ReferenceError
错误。
6、成功的RHS查询,对变量进行不合理的操作,会抛出TypeError
错误。
7、非严格模式下
,LHS查询如果找不到变量,会自己生成一个变量。
都已经读到这里了,动动您贵手,点赞再走
,祝你2021年,要啥都有。
我是阿飞,一个GTD践行者,深度工作践行者。
广告Time:
我做了一个公众号:青柠檬读书会
,我希望成长的路上,有你相伴。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!