引擎在执行代码时,如var a = 2
。会通过查找判断它是否已经被声明。查找有两个类型:
LHS(Left-Hand Side)
:通常出现在=
的左边。查询会试图找到变量的容器本身RHS(Right_Hand Side)
:通常出现在=
的右边。查询会试图找到该变量的值
这里的L
或者R
是相对于=
而言。
var a = 1;
console.log(a);
上述代码运行时,在第一行中,对a
进行了LHS
查询,去获取a
的容器本身,此时我们并不关心a
是什么值;然后为a
容器赋值为2。在第二行中,对a
进行了RHS
查询,去获取a
的当前值。
小测验
思考一下,下面的代码中有几处LHS
查询,几处RHS
查询?
function foo(a) {
console.log(a);
}
foo(2);
答案是:1处LHS
,3处RHS
。
首先调用foo
方法时,需要进行一次RHS
查询,找到foo
的定义;代码中a=2
是一个很容易被忽略的细节,它发生在2被当做参数传递给foo
时,2会被分配给a
,此时需要对a
做一次LHS
,获取a
的容器;然后console.log
时,其实对console
也进行了一次RHS
查询,找到它的值,并获取其中的log
方法。最后就是输出a
时,对a
做了一次RHS
,获取a
的值。
异常
如果对变量进行查询时通过作用域链无法获取,就会出现异常。
对于LHS
:如果没有找到,在非严格模式下会自动在全局作用域中创建一个同名变量;在严格模式下会抛出ReferenceError
的错误。
对于RHS
:如果没找到同样会抛出ReferenceError
的错误;如果找到了,但是对该变量的操作不合法(如:该变量此时是undefined
,我们却以函数的形式调用它),会抛出TypeError
的错误。
即ReferenceError
同作用域判别失败有关;TypeError
同判别成功,但操作不合法有关。