作用域是什么

编译原理

  • 分词/词法分析
  • 解析/语法分析
  • 代码生成

理解作用域

常用名词

  • 引擎
    从头到尾负责整个JavaScript程序的编译及执行过程。
  • 编译器
    引擎的好朋友之一,负责语法分析及代码生成等脏活累活
  • 作用域
    引擎的另一位好朋友, 负责收集并维护由所有声明的标识符( 变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

过程

var a = 2;

  • 遇到var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。 如果是, 编译器会忽略该声明, 继续进行编译; 否则它会要求作用域在当前作用域的集合中声明一个新的变量,并命名为a。
  • 接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理a = 2这个赋值操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作a的变量。如果是,引擎就会使用这个变量;如果否,引擎会继续查找该变量,直到全局变量。

术语

  • LHS
    如果查找的目的是对变量进行赋值,那么就会使用LHS查询
  • RHS
    如果目的是获取变量的值,就会使用RHS查询

LHS和RHS查询都会在当前执行作用域中开始, 如果有需要( 也就是说它们没有找到所需的标识符),就会向上级作用域继续查找目标标识符, 这样每次上升一级作用域( 一层楼) ,最后抵达全局作用域(顶层),无论找到或没找到都将停止。不成功的RHS引用会导致抛出ReferenceError异常。 不成功的LHS引用会导致自动隐式地创建一个全局变量( 非严格模式下),该变量使用LHS引用的目标作为标识符, 或者抛出ReferenceError异常(严格模式下)。

小结

作用域是一套规则, 用于确定在何处以及如何查找变量( 标识符)。如果查找的目的是对变量进行赋值,那么就会使用LHS查询;如果目的是获取变量的值,就会使用RHS查询。