作用域时根据名称查找变量的一套规则。实际情况中,通常需要同时顾及几个作用域。
当一个块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套。因此,在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域于中继续查找,知道找到该作变量。或抵达最外层的作用域(也就是全局作用域)为止。
例:
Function foo(a){
Console.log(a+b);
}
Var b= 2;
Foo(2);//4
对 b 进行的 RHS 引用无法在函数 foo 内部完成,但可以在上一级作用域(在这个例子中就是全局作用域)中完成。
遍历嵌套作用域链的规则很简单:引擎从当前的执行作用域开始查找变量,如果找不到,就向上一级继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找过程就会停止。
为什么区分 LHS 和 RHS 是一件很重要的事?
因为在变量还没有声明(在任何作用域中都无法找到该变量)的情况下,这两种查询的行为是不一样的。
例:
Function foo(a){
Console.log(a+b);
b = a;
}
Foo(2);
第一次对 b 进行 RHS 查询时是无法找到该变量的。也就是说,这是一个 “未声明” 的变量,因为在任何相关的作用域中都无法找到它。
如果 RHS 查询在所有的作用域中遍寻不到所需的变量,引擎就会抛出 ReferenceError 异常。值得注意的是,ReferenceError 是非常重要的异常类型。
相较之下,当引擎执行 LHS 查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非 “严格模式” 下。
ES5 中引入了 “严格模式”。同正常模式,或者说宽松 / 懒惰莫斯相比,严格模式在行为上有很多不同。其中一个不同的行为是严格模式禁止自动或隐式的创建全局变量。因此,在严格模式中 LHS 查询失败时,并不会创建并返回一个全局变量,引擎会抛出同 RHS 查询失败时类似的 referenceerror 异常。
接下来,如果 RHS 查询找到了一个变量,但是你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或者引用 null 或 undefined 类型的值中的属性,那么引擎会抛出另外一种类型的异常,叫作 type error。
ReferenceError 同作用域判别失败相关,而 type error 则代表作用域判别成功了,但是对结果的操作是非法或者不合理的