js引擎查询 LHS RHS(消化ing)

赋值操作的目标是谁(LHS),谁是赋值操作的源头(RHS)

LHS(Left-hand Side):当1付给a变量,要先查询a是否存在,即查找容器本身,这时候用的就是LHS查询

RHS(Right-hand Side):要获取某个变量的值,比如打印a变量,console.log(a);js引擎要去查询这个变量是否存在,得到变量的值,即查找容器的值,这个时候用的就是RHS查询


LHS查询比较松散,如果查询不到,就会创建一个全局变量,不会抛出异常

RHS查询比较严格,如果查询不到的话就会抛出异常,因为你要获取某个变量指向的值,可是根本就没有那个变量,只能抛出异常

如:var a = 2

这句代码会被分成两部分来执行var a 和a= 2; 并且一个是在代码执行前的预编译进行一个在引擎运行时执行。虽然这里的a是同一个变量但引擎两次查找这个变量的方式却是不一样的。

当代码进行编译时,浏览器引擎看到var关键字,意味着这里需要声明变量会首先对a进行LHS查询。查询当前作用域中是否存在a这个标识符,如果存在浏览器引擎会忽略本次声明,如果没有会在作用域中声明一个标识符a。编译完成后浏览器看到a=2,会对a进行RHS查询,查找当前作用域中是否成在a这个变量或者说是容器,如果有就把2赋值给a,如果没有,引擎就会抛出 ReferenceError 异常。

如:function foo(a){ var b=a; return a+b; }

  var c=foo(2);

代码中有三处LHS,四处RHS

(1)从 var c = foo( 2 );入手.
c的赋值操作需要对c进行一次LHS查询,foo(2)需要进行一次RHS查询,去获取 foo(2) 的值.
(2)进入函数声明,foo(a){},这里有一个隐式赋值操作,
需要对a进行一次LHS查询,判断作用域中是否存在名为a的变量,若存在则直接赋值a=2;
若不存在,如果是严格模式下,则报ReferenceError:a is not defined.
如果非严格模式,则创建一个a的全局变量,并直接赋值a=2;
(3)var b = a;需要对b进行一次LHS查询,以及对a进行一次RHS查询以获得a的值;
(4)return a + b;需要分别对a和b进行RHS查询;

小结:

作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。

如果查找的目的是对变量进行赋值,就会使用 LHS 查询;如果目的是获取变量的值,就会用 RHS 查询。

赋值操作会导致 LHS 查询。 = 操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作, 即都会导致 LHS 查询。

JavaScript 引擎首先会在代码执行前对其进行编译,在这个过程中,像var a = 2 这样的声明会被分解成两个独立的步骤:
1.首先,var a在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。
2.接下来,a = 2会查询(LHS查询)变量 a 并对其进行赋值。

LHS 和 RHS
查询都会在当前执行作用域中开始,如果有需要(也就是说它们没有找到所需的标识符),就会向上级作用域继续查找目标标识符,这样每次上升一级作用域,最后到达全局作用域,无论找到或没找到都将停止。

不成功的 RHS 引用会导致抛出 ReferenceError 异常。不成功的 LHS引用会导致自动隐式地创建一个全局变量(非严格模式下),该变量使用 LHS 引用的目标作为标识符,或者抛出ReferenceError异常(严格模式下)。

 

上一篇:作用域


下一篇:提高可测性-Mock平台设计和整体规划