JavaScript的查询机制LHS和RHS解析
JavaScript引擎在查找一个变量的时候,有两种查找机制:LHS和RHS。
RHS的查询是简单地查找到某个变量的值,而LHS则是试图找到变量的容器的本身。
一个简单的例子:当我们执行console.log(a)时,执行的就是RHS,因为这里a并没有赋予任何的值。相应的,需要查找并取得a的值,这样才能将值传递给conso.log(..)。
而当我们执行到a=2时,这里对a的引用就是LHS引用,因为实际上我们并不关心当前的值是什么,只是想要为=2这个赋值操作找到一个目标。
需要注意的是:
当我们执行以下代码:
functionfoo(a){ console.log(a);//2 } foo(2);
这里对foo的调用执行了RHS引用,但还有一个隐式的a=2的操作,这里又执行了一个LHS引用。
我们通常把functionfoo(a){}转变为varfoo,foo=function(){},如果这样理解的话,这个函数声明会执行LHS查询,但是在引擎执行代码的时候,并不会有线程专门用来将一个函数值“分配给”foo。所以,将函数声明理解成赋值的LHS查询的形式并不合适。
区分LHS和RHS是一件很重要的事。如果RHS查询在作用域链中找不到需要的变量,会抛出ReferenceError的异常。
functionfoo(a){ console.log(a+b); } foo()
以上代码会抛出异常:bisnotdefined
相比之下,如果JavaScript引擎执行的是LHS查询,如果一直到顶层的作用域(全局作用域)中都没有找到目标变量的话,它就会在全局作用域中声明一个具有目标名称的变量,并将其返回给引擎。(非严格模式下,严格模式下会禁止自动创建或隐式创建全局变量)
functionfoo(a){ b=a;//b=2 } foo(2)
上面的代码执行的LHS查询,在非严格模式下,JavaScript引擎在全局作用域中没有找到b,所以它就在全局作用域中声明了一个变量b。所以此时结果不会报错且b被赋值为2。
总结:
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。如果查找的目的是对变量进行赋值,就会使用LHS查询;如果目的是获取变量的值,就会使用RHS查询。
=操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作。
LHS和RHS查询都会在当前执行作用域中开始,如果有需要(当前没找到),就会向上级作用域继续查找目标标识符(作用域链)。
不成功的RHS会导致抛出ReferenceError异常。不成功的LHS会自动隐式在全局作用域中创建一个全局变量(非严格模式下),该变量使用LHS引用的目标作为标识符。(如果是严格模式下也会抛出ReferenceError异常)。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。