JavaScript中在预编译后执行代码时对变量的查询分为LHS(Left-Hand-Side)查询和RHS(Right-Hand-Side)查询。
一、LHS和RHS有什么区别?
这里的L和R是指赋值时候“=” 的左侧还是右侧,也就是说一个是做被赋值,一个是取值。
正如下面这个例子,对变量a的引用是一个LHS引用,而对值2的引用是RHS引用
var a = 2
当然,在js中赋值操作不仅仅限于“=”这种显式赋值。还有一些隐式的赋值,比如:
function foo(a){
...
}
foo(2);
这个例子中,执行函数foo的时候对foo进行了RHS引用,而对foo函数进行调用的时候隐藏着一个将2赋值给形式参数a的过程,即a=2
,这里有对a的LHS引用。
二、为什么要区分LHS引用和RHS引用?
这两种不同的引用方式的在对没有声明的变量的处理上是不同的。而这个不同之处对于我们编写代码和分析JS引擎报的错误是很有用处的。
当对一个变量执行RHS查询时,如果遍历该变量所在处的词法作用域未能找到这个变量,JS引擎就会抛出 ReferenceError 错误如果成功查询到了这个变量,但是对这个变量执行不合理操作,比如对一个非数组的变量执行下标取值,JS引擎就会抛出 TypeError 错误。
当对一个变量执行LHS查询时,同样在遍历作用域后无法找到该变量,在非ES5的严格模式下,系统就会自动在全局作用域中创建一个同名变量,并将引用转移到该新建的全局变量中。而在ES5的严格模式下,LHS查询失败时JS引擎会抛出一个同RHS一样的 ReferenceError 错误。
因此,对LHS查询和RHS查询的仔细区分和理解无论是对JS执行过程本身的理解还是分析错误都是有所好处的。