变量的赋值会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),
然后运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值。
LHS和RHS
LHS和RHS的含义是”赋值操作的左侧或右侧”并不一定意味着”=赋值操作的左侧和右侧”。赋值操作
还有其他几种形式,因此在概念上最好理解为”赋值操作的目标是谁(LHS)”以及”谁是赋值操作的源
头(RHS)”。
作用域嵌套
当一个块或函数嵌套在另一个块或函数中时,就发生了作用域嵌套。因此,在当前作用域中无法找
到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域
(也就是全局作用域)为止。
RHS和LHS
如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常。
当引擎执行LHS查询时,如果在顶层中也无法找到目标变量,全局作用域就会创建一个具有该名称的
变量,并将其返回给引擎,前提是程序运行在”非严格模式”下。ES5引入了严格模式,严格模式禁止
自动或隐士地创建全局变量。因此,在严格模式中LHS查询失败时,并不会创建并返回一个全局变量,
引擎会抛出同RHS查询失败时类似的ReferenceError异常。ReferenceError同作用域判别失败相关,
而TypeError则代表作用域判别成功了,但是对结果的操作是非法或不合理的。
总结
作用域是一套规则,用于确定在何处以及如何查找变量。如果查找的目的是对变量进行赋值,那么
会使用LHS查询;如果目的是获取该变量的值,就会使用RHS查询。
JavaScript引擎首先会在代码执行前对其进行编译,在这个过程中,像var a = 2
这样的声明会
被分解成两个独立的步骤:
- 首先,
var a
在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。- 接下来,
a = 2
会查询(LHS查询)变量a对其进行赋值。