JavaScript引擎LHS查找和RHS查找

 

要想真正理解Javascript脚本中每一句代码的执行过程,需要弄清楚几个基本概念:1、引擎,从头到尾负责整个 JavaScript 程序的编译及执行过程。2、编译器,引擎的好朋友之一,负责语法分析及代码生成等脏活累活。3、作用域,引擎的另一位好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查 询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

例如var a=2;看引擎和编译器是如何处理这段代码的,处理过程:

1. 遇到 var a,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的 集合中。如果是,编译器会忽略该声明,继续进行编译;否则它会要求作用域在当前作 用域的集合中声明一个新的变量,并命名为 a。 2. 接下来编译器会为引擎生成运行时所需的代码,这些代码被用来处理 a = 2 这个赋值 操作。引擎运行时会首先询问作用域,在当前的作用域集合中是否存在一个叫作 a 的 变量。如果是,引擎就会使用这个变量;如果否,引擎会继续查找该变量(查看 1.3 节)。 如果引擎最终找到了 a 变量,就会将 2 赋值给它。否则引擎就会举手示意并抛出一个异 常!

总结:变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如 果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对 它赋值。

为了进一步理解引擎的工作过程,可以了解下面两个概念LHS查询和RHS查询。字面的理解就是,当变量出现在赋值操作的左侧时进行 LHS 查询,出现在右侧时进行 RHS 查询。

例如

console.log(a).

其中对 a 的引用是一个 RHS 引用,因为这里 a 并没有赋予任何值。相应地,需要查找并取 得 a 的值,这样才能将值传递给 console.log(..)。

相比

a=2

这里对 a 的引用则是 LHS 引用,因为实际上我们并不关心当前的值是什么,只是想要为 = 2 这个赋值操作找到一个目标。

再给一个相对复杂的例子:

function foo(a)

{ console.log( a ); // 2 }

foo( 2 );

最后一行 foo(..) 函数的调用需要对 foo 进行 RHS 引用,意味着“去找到 foo 的值,并把 它给我”。并且 (..) 意味着 foo 的值需要被执行,因此它最好真的是一个函数类型的值!

代码中隐式的 a=2 操作可能很容易被你忽略掉。这个操作发生在 2 被当作参数传递给 foo(..) 函数时,2 会被分配给参数 a。为了给参数 a(隐式地)分配值,需要进行一次 LHS 查询。

这里还有对 a 进行的 RHS 引用,并且将得到的值传给了 console.log(..)。console. log(..) 本身也需要一个引用才能执行,因此会对 console 对象进行 RHS 查询,并且检查 得到的值中是否有一个叫作 log 的方法。

原文地址:https://www.cnblogs.com/harlinhan/p/5757217.html