本文基于《你不知道的Javascript》编写。
JavaScript中在预编译后执行代码时对变量的查询分为LHS(Left-Hand-Side)查询和RHS(Right-Hand-Side)查询。
是一个赋值操作的左侧和右侧的意思;
(一)看一个转换后的例子:
function foo(a) {
console.log( a ); // 2 } foo( 2 );
代码执行原理图解:

(二)我的分析
示例:
- 找到其中所有的 LHS 查询。
- 找到其中所有的 RHS 查询。
function foo(a) {
var b = a; return a + b; } var c = foo( 2 );
分析:
(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 是一件重要的事情?
function foo(a) {
console.log( a + b ); b = a; }foo( 2 );
(四)小结
- 作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。
- 如果查找的目的是对变量进行赋值,就会使用 LHS 查询;如果目的是获取变量的值,就会用 RHS 查询。
- 赋值操作会导致 LHS 查询。 = 操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作, 即都会导致 LHS 查询。
- JavaScript 引擎首先会在代码执行前对其进行编译,在这个过程中,像var a = 2 这样的声明会被分解成两个独立的步骤:
1.首先,var a在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。
2.接下来,a = 2会查询(LHS查询)变量 a 并对其进行赋值。 - LHS 和 RHS
查询都会在当前执行作用域中开始,如果有需要(也就是说它们没有找到所需的标识符),就会向上级作用域继续查找目标标识符,这样每次上升一级作用域,最后到达全局作用域,无论找到或没找到都将停止。
- 不成功的 RHS 引用会导致抛出 ReferenceError 异常。不成功的 LHS引用会导致自动隐式地创建一个全局变量(非严格模式下),该变量使用 LHS 引用的目标作为标识符,或者抛出ReferenceError异常(严格模式下)。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214759.html原文链接:https://javaforall.net
