资讯专栏INFORMATION COLUMN

快速理解JavaScript 中的 LHS 和 RHS 查询

lemon / 698人阅读

摘要:如果查找的目的是对变量进行赋值,就会使用查询如果目的是获取变量的值,就会用查询。赋值操作会导致查询。接下来,会查询查询变量并对其进行赋值。不成功的引用会导致抛出异常。

简述编译原理

JavaScript 程序中的一段源代码在执行之前会经历三个步骤,统称为 编译

分词/词法分析

解析/语法分析

代码生成

先看原书对一个赋值操作的拆解说明:

变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值。 --- 《你不知道的JavaScript(上卷)》 P7

而要讲的 LHSRHS 就是上面说的对变量的两种查找操作,查找的过程是由作用域(词法作用域)进行协助,在编译的第二步中执行。

LHS 和 RHS

字面意思其实是 Left Hand SideRight Hand Side 即左手边和右手边

一般可以理解为 赋值操作的左侧和右侧

先看个例子一
console.log(a);

这里对 a 是一个 RHS 引用,因为 a 并没有赋予任何值,目的是为了取到 a 的值并打印出来。

a = 2;

这里对 a 是一个 LHS 引用,因为实际上我们不关心当前的值是什么,只是想要把 a 赋值为 2。

再看例子二
function foo(a) {
    console.log(a); // 2
}
foo(2);

最后一行foo(..)函数的调用需要对 foo 进行 RHS 引用,意味着是取到 foo 的值,并且 (..)意味着 foo 需要被执行,因此它最好是一个函数类型的值

其中有一个容易被忽略的隐式赋值操作 a = 2,它发生在 2 被当做实参传入 foo 中时。即实参 2 传给了形参 a,需要一个 LHS 查询

console 那一行还有对 a 的一次 RHS 引用(或者叫查询),同时console.log(..)本身也需要一个 RHS 引用,即对 console 对象进行 RHS 查询,并且检查得到的值中是否有一个叫做 log 的方法。

书中有一段引擎和作用域的对话,有助于很好的理解例子二,see YDKJS github

小测验
function foo(a) {
    var b = a;
    return a + b;
}
var c = foo(2);

试试找出其中的3处 LHS 查询,4处 RHS 查询

答案

LHS 查询:

c = ..;

a = 2(隐式变量分配)

b = ..

RHS 查询

foo(2..

= a;

a ..

.. b

小结

参考原书中文版P12,英文版见 github

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

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

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

JavaScript 引擎首先会在代码执行前对其进行编译,在这个过程中,像var a = 2 这样的声明会被分解成两个独立的步骤:

首先,var a在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。

接下来,a = 2会查询(LHS查询)变量 a 并对其进行赋值。

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

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

参考

我的blog 原文:JS-LHS-RHS

You Dont Know JS

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87266.html

相关文章

  • JS编译之 LHS RHS(你不知道的JavaScript 小记一)

    摘要:关于两个专业术语的讨论起自对你不知道的一书的阅读学习。遇到,编译器会询问作用域是否已经有一个该名称的变量存在于同一个作用域的集合中。摘录来自你不知道的。 JS 编译之 LHS RHS 一、前言 最近和朋友聊技术的时候,聊到 LHS RHS,我竟然没听说过 没听说过。。。 于是成功引起了我的好奇心。 关于两个专业术语的讨论起自对《你不知道的JavaScript》一书的阅读学习。 二、编译...

    Cristic 评论0 收藏0
  • JavaScript中作用域相关的那些点

    摘要:本文为你不知道的上卷中关于作用域相关的知识点的总结。第一层代表当前作用域,大楼的顶层代表全局作用域。如果一定要找一个点与动态词法作用域扯上关系的话,那就是值了。 本文为《你不知道的JavaScript(上卷)》中关于作用域相关的知识点的总结。 作用域 赋值操作 变量的赋值操作实际上有两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找...

    coolpail 评论0 收藏0
  • javascript作用域闭包之我见

    摘要:查询是在作用域链中,一级级的往上查找该变量的引用。作用域和作用域链作用域的概念,应该两张图几句话就能解释吧。这个建筑代表程序中的嵌套作用域链。一层嵌一层的作用域形成了作用域链,变量在作用域链中的函数内得到了自己的定义。 javascript作用域和闭包之我见 看了《你不知道的JavaScript(上卷)》的第一部分——作用域和闭包,感受颇深,遂写一篇读书笔记加深印象。路过的大牛欢迎指点...

    SoapEye 评论0 收藏0
  • JavaScript 作用域不完全指北

    摘要:一旦到达顶层全局作用域,可能找到,也可能没有找到,查找过程都必须停止。当引擎执行查询时,如果查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出异常。代表作用域判别失败相关,而则代表作用域判别成功了,但是对结果的操作是非法或不合理的。 什么是作用域 对于几乎所有编程语言,最基本的功能之一就是能够存储变量的值,并且能在之后对这个值进行访问和修改。这样就会带来几个问题,这些变量存储在哪...

    coordinate35 评论0 收藏0
  • 理解 JavaScript 作用域

    摘要:作用域链前面说,作用域是根据名称查找变量的一套规则。把这样一层一层嵌套的作用域,叫做作用域链。因为这个函数名无法被外部作用域所访问。的进阶用法是给其传入参数这样的好处是可以缩短查询时的作用域链。 上一篇文章中分析了 JS 中的数据类型和变量。这一篇文章将分析作用域,以及回答上一篇文章中变量提升的原因。 什么是作用域 作用域是一套规则,保存着变量,等待被引擎所查找。 var a = 1;...

    dadong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<