理解作用域
在我们编写好js代码以后,要经过js引擎的编译才能被计算机执行,了解代码的编译过程会帮助你理解什么是作用域。
好了,下面,我们将要开始一台大戏,准备好瓜子西瓜,我们来看戏了:
首先公布演员表:
- 引擎
从头到尾负责整个JavaScript 程序的编译及执行过程。
- 编译器
引擎的好朋友之一,负责语法分析及代码生成等脏活累活(详见前一节的内容)。
- 作用域
引擎的另一位好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
演员及其演出角色布置完毕,下面来布置一下舞台。
我们以 var a = 2;为例,来说明js编译及执行的过程。
开演
先是编译器登场,开始对代码进行编译,当然,这个过程是需要作用域进行配合的,所以这个场景需要两位演员===> 作用域,编译器。开始:
编译器:“苦逼啊,又要干活了,我看看..,还好这次就一句代码。”
编译器 工作中.......(看到了var a = 2这句代码)
编译器:“作用域啊,你找找你有没有a这个玩意。”
作用域:“好嘞,我找找,...... ,没有,你把它给我,我给你存了。”
编译器:“给,一会可能引擎就问你要了。”
第一场结束,接下来第二场(引擎执行代码)
编译器:“引擎啊,我编译完了,你开始执行吧。”
引擎:“好,给我吧。”
引擎开始执行........(看到编译后的 var a = 2)
引擎:“作用域啊,a这个玩意你有没有。”
作用域:“有啊,我给你。”
引擎:“好嘞!”
(谢幕)
上面这场戏,会有同学看得云里雾里的感觉,因为你会疑惑,为什么引擎和编译器都要问作用域要 a ,这里我要解释一下为什么:
代码 var a = 2;其实在编译时是分成两句的 var a ,a = 2;是这样的两句,第一句是编译时执行,第二句是引擎执行时执行的。所以就是这个过程,当编译器编译的时候,会将 a 存入作用域,当引擎执行时就会像作用域询问 a 在当前环境下有没有访问权限,如果有就将 2 赋值给 a ,如果没有就报错。看到这,在回过头来看看上面的对话,是不是清晰了很多呢?
但是你肯定会有疑问,为什么要分成 var a,a = 2;两句进行呢?他是怎么实现呢?因为又是一个非诚庞大的知识点,这里只是简单的说一下,首先是 var a,在编译时会生成一段代码,这段代码是帮助引擎在内存中查找 a 在作用域中的位置的,也就是引起引擎像作用域发起询问的代码,当编译器第一次遇到 var a 时,会要求作用域将 a 储存起来,以方便在后面的使用。当引擎执行到 a = 2 时,就会像作用域询问 a 的储存地址,将 2 储存进内存,这就是简单的过程,实际操作的过程还很复杂,有兴趣的同学可以自行学习。
现在,我们就可以根据上面的讲解去理解作用域了。首先,什么是作用域:作用域就是js储存变量可和取用变量的一套严格的规则。
这样子看作用域是不是就变得很简单了,对于一个变量,我们要以什么样的方式去存,又要以什么样的方式去拿,js引擎为我们定义好了这样的一套规则,我们按照这套规则去使用变量,如果你有越界的行为,js就会用报错的方式提示你,你对变量的操作越界了,马上改回来。
这就是从js编译的角度去理解作用域,当然,由于水平限制,文章中有错误与不足之处还望留言之处,谢谢。