什么是作用域?
一种程序设计语言必然会使用到变量,而优秀的变量的存储和访问的逻辑设计可以使得语言执行效率有很大提升,JS中的变量的存储和访问的系统称为其作用域系统,也可以说是存储和访问的规则
常见的编译语言在执行之前经历的三个阶段
- 分词/词法分析 代码字符串分离出有意义的词法单元,过程是有状态的则称为词法分析,否则就是简单分词
- 语法/语法分析 众多的词法单元组合生成一棵树,抽象语法树(AST)
- AST 转换成可执行文件,可以是机器码
js代码执行的过程
编译器读取js代码,识别到声明语句就通知作用域生成相关的变量,同时对于不是声明语句也就是需要执行的动作,编译器生成相关代码交给js执行引擎去执行,引擎执行代码过程中会访问作用域获取需要的变量,也更新一些变量
结论:js代码编译的时刻在执行之前,简单说,首先编译器遍历代码,声明变量,同时生成可执行代码,做好了准备,然后引擎开始执行
执行过程中如何访问变量呢?作用域查询变量的方式
分为LHS和RHS,LHS查询是找到这个变量的目标位置,给其赋值,不关注其原来的值;RHS查询的是变量原来的值,然后可能会使用这个值,而不对变量作处理
作用域嵌套
一段代码块有它的作用域区域范围,如果存在一个代码块在另一个代码块内部呢?这种情况下,作用域被设计成是可嵌套的,内层代码执行时,访问变量,内层找不到就往外层找,一直找到全局作用域,若还不存在,则抛出异常
为什么作用域查找变量需要区分LHS和RHS?
(非严格模式下)当变量没有被声明的情况下,这两种查询或者说引用方式,会导致不同的结果;LHS,作用域会好心自动生成这样的一个变量;RHS,抛出ReferenceError
作用域小结
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。如果查找的目的是对变量进行赋值,那么就会使用 LHS 查询;如果目的是获取变量的值,就会使用 RHS 查询。 ——来自原书《你不知道的JS》