目录

1、LHS(Left Hand Side)和 RHS(Right Hand Side)

2、实例详解

3、总结


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

而要讲的 LHS 和 RHS 就是上面说的对变量的两种查找操作,查找的过程是由作用域(词法作用域)进行协助,但是引擎执行怎样的查找, 会影响最终的查找结果。

1、LHS(Left Hand Side)和 RHS(Right Hand Side)

当变量出现在赋值操作的左侧时进行 LHS 查询, 出现在右侧时进行 RHS 查询。讲得更准确一点, RHS 查询与简单地查找某个变量的值别无二致, 而 LHS 查询则是试图找到变量的容器本身, 从而可以对其赋值。 从这个角度说, RHS 并不是真正意义上的“赋值操作的右侧”, 更准确地说是“非左侧”。  ----《你所不知道的JavaScript(上)》 P7

  简单来说,

  (1)LHS查询指的是找到变量的容器本身,从而可以对其进行赋值。也就是找到赋值操作的目标。LHS查询的时候会沿着作用域链进行查询,找到的话就会将值赋值给这个变量,如果到达作用域顶端仍然找不到,就会在作用域链顶端创建这个变量(在严格模式中 LHS 查询失败时, 并不会创建并返回一个全局变量, 引擎会抛出同 RHS 查询失败时类似的 ReferenceError 异常) 

var a = 2;

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

  (2)RHS查询就是普通的查询变量的值,即获取变量的值。RHS查询的时候会沿着作用域链进行查询,找到的话就会取得这个值并返回,如果到达作用域顶端仍然找不到,引擎就会抛出 ReferenceError异常如果 RHS 查询找到了一个变量, 但是你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用, 或着引用 null 或 undefined 类型的值中属性, 那么引擎会抛出另外一种类型的异常, 叫作 TypeError。
(注:ReferenceError 同作用域判别失败相关, 而 TypeError 则代表作用域判别成功了, 但是对结果的操作是非法或不合理的。)

举个栗子:

console.log(a);

这里的a就是一个RHS引用,因为console.log需要获取到a的值才能输出a的值。当然这里的console.log也是一个RHS引用,这里对console 对象进行RHS 查询,并且检查得到的值中是否有一个叫作log 的方法。例子中的a因为没有声明过,所以会抛出错误。如下图所示:

2、实例详解

实例1:

function foo(a) {console.log( a );
}foo( 2 );

(1)foo(..) 函数的调用需要对 foo 进行RHS引用 ,意思是“去找到 foo 的值, 并把它给我 ”。

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

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

所以这里一共进行了1次LHS查询3次RHS查询。

让我们把上面这段代码的处理过程想象成一段对话, 这段对话可能是下面这样的。

  引擎: 我说作用域, 我需要为 foo 进行 RHS 引用。 你见过它吗?

  作用域: 别说, 我还真见过, 编译器那小子刚刚声明了它。 它是一个函数, 给你。

  引擎: 哥们太够意思了! 好吧, 我来执行一下 foo。

  引擎: 作用域, 还有个事儿。 我需要为 a 进行 LHS 引用, 这个你见过吗?

  作用域: 这个也见过, 编译器最近把它声名为 foo 的一个形式参数了, 拿去吧。

  引擎: 大恩不言谢, 你总是这么棒。 现在我要把 2 赋值给 a。

  引擎: 哥们, 不好意思又来打扰你。 我要为 console 进行 RHS 引用, 你见过它吗?

  作用域: 咱俩谁跟谁啊, 再说我就是干这个。 这个我也有, console 是个内置对象。给你。

  引擎: 么么哒。 我得看看这里面是不是有 log(..)。 太好了, 找到了, 是一个函数。

  引擎: 哥们, 能帮我再找一下对 a 的 RHS 引用吗? 虽然我记得它, 但想再确认一次。

  作用域: 放心吧, 这个变量没有变动过, 拿走, 不谢。

  引擎: 真棒。 我来把 a 的值, 也就是 2, 传递进 log(..)。

  ----《你所不知道的JavaScript(上)》 P9

实例2:

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

以上代码中有3个LHS与4个RHS,分析如下:

(1)var c中的c需要被赋值,在赋值操作的左侧,所以对c进行LHS引用。

(2)变量c需要被赋值,他的值是foo(2),那么foo(2)的值是多少呢,需要查找foo(2)的值,在赋值操作的右侧,所以对foo(2)进行了一次RHS查询。

(3)隐含赋值操作,将2传递给function foo(a){……}函数的参数a,a=2,a在赋值操作的左侧,对a进行了一次LHS查询。

(4)var b=a;中,b需要被赋值,处在赋值操作的左侧,所以对b进行了一次LHS查询,b的值将从a来,那么右侧的a的值从何而来呢?这就需要对赋值操作右侧的a进行了一次RHS查询。

(5)return a+b;中,需要找到a与b的值的来源,a与b都在赋值操作的右侧,才能得到a+b的值,所以对a与b都是进行一次RHS查询。

注:console.log(..) 本身也需要一个引用才能执行,因此会对console 对象进行RHS 查询,并且检查得到的值中是否有一个叫作log 的方法。这里不会再对log进行RHS查询。因为对console查询完毕后,对象属性访问规则会接管对log属性的访问。也就是说,如果是访问对象的属性就不存在LHS查询和RHS查询了,找不到就返回undefined。

3、总结

如果查找的目的是对变量进行赋值, 那么就会使用 LHS 查询; 如果目的是获取变量的值, 就会使用 RHS 查询。赋值操作符会导致 LHS 查询。 =操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作。JavaScript 引擎首先会在代码执行前对其进行编译, 在这个过程中, 像 var a = 2 这样的声明会被分解成两个独立的步骤:

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

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

LHS 和 RHS 查询都会在当前执行作用域中开始, 如果有需要(也就是说它们没有找到所需的标识符), 就会向上级作用域继续查找目标标识符, 这样每次上升一级作用域, 最后抵达全局作用域, 无论找到或没找到都将停止。不成功的 RHS 引用会导致抛出 ReferenceError 异常。 不成功的 LHS 引用会导致自动隐式地创建一个全局变量(非严格模式下), 该变量使用 LHS 引用的目标作为标识符, 或者抛出 ReferenceError 异常(严格模式下)。

LHS 和 RHS---你所不知道的JavaScript相关推荐

  1. 你所不知道的 JavaScript

    目录 一.作用域和闭包 1. 附录B 块作用域的替代方案 1.1 Traceur - 将ES6 代码生成兼容ES5的工具 1.2 隐式和显式作用域 2. 附录C this 词法 二.this 和对象原 ...

  2. 你所不知道的setTimeout

    JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务.初始接触它的人都觉得好简单 ...

  3. 互联网人群画像和你所不知道的真相

    作为新时代互联网营销的关键部分,人群画像引起了诸多兴趣,近年颇为风靡.几乎所有的互联网广告供应商都不约而同的强调,他们有足够精确的人群画像数据,确保能够找到广告主真正的受众.但是事情果真如此吗?人群画 ...

  4. 一些你所不知道的VS Code插件

    摘要: 你所不知道的系列. 原文:提高 JavaScript 开发效率的高级 VSCode 扩展之二! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 作为一名业余爱好者.专业人员,甚 ...

  5. 高手才知道!七个你所不知道的 D3.js 秘技

    D3.js ,当前最火红的视觉化套件,你用过了吗?越来越多人使用 D3.js 来开发视觉化专题,但- 你对 D3.js 的了解又到哪里呢?这次我们就带大家一起来看看一些 D3.js 很重要.大家却又普 ...

  6. 那些你所不知道的arXiv使用技巧

    作者:Tom Hardy Date:2020-12-23 来源:那些你所不知道的arXiv使用技巧

  7. 系统调优,你所不知道的TIME_WAIT和CLOSE_WAIT

    https://my.oschina.net/fdhay/blog/638631 高性能网络 | 你所不知道的TIME_WAIT和CLOSE_WAIT 2016-02-18 大房 大房说 本文是我将最 ...

  8. ai的弹窗点了都不响应_【评价集合】拼多多评价,你所不知道的点都在这里!...

    对于在拼多多开店的商家们来说,评价是消费者对于商品的好坏程度的一个评分,评价的高低不仅仅会影响到商品的销量,更会影响转化率以及权重!所以为了店铺商品的长远发展打算!各位商家在求取出评.好评的道路上不断 ...

  9. python 函数调用 不允许关键字参数_你所不知道的Python|函数参数的演进之路

    原标题:你所不知道的Python|函数参数的演进之路 函数参数处理机制是Python中一个非常重要的知识点,随着Python的演进,参数处理机制的灵活性和丰富性也在不断增加,使得我们不仅可以写出简化的 ...

最新文章

  1. server side render
  2. 【资源】媲美搜索神器everything,超过1秒出结果算我输!
  3. kotlin 判断数字_Kotlin程序检查数字是偶数还是奇数
  4. 【poj题集整理】【存下来并不会看】
  5. 【译】NoClassDefFoundError和ClassNotFoundException的不同
  6. P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题(2022.02.02) --- python3实现
  7. 网易严选搜索推荐实践之:“全能选手”召回表征算法实践.pdf(附下载链接)...
  8. css3中定义required,focus,valid和invalid样式
  9. 华为Java开发编程最新军规,谁违反谁滚蛋!
  10. laravel 验证手机号
  11. Ecma 118th GA会议手记
  12. 软件测试高薪“骗局”软件测试入门就月薪过万,还包就业。别再上当受骗了、清醒点吧
  13. 移植AT91Bootstrap1.15
  14. 2021 百度网盘网页版 倍速播放技巧(亲测有效)
  15. 纯正体验,极致商务 | 丽亭酒店聚焦未来赛道,实现共赢发展
  16. 腾讯御安全深度解析新型流量盗刷病毒家族
  17. postgis常用的函数
  18. 【行为管理篇】01. 恢复出厂及登录 ❀ 深信服上网行为管理
  19. 公式自动编号/居中对齐、插入脚注、文献引用等,让恼人的文章格式从此有据可循
  20. Zookeeper 面试题及答案

热门文章

  1. 关于面试总结2-SQL学生表
  2. 定义复数java_java定义复数的方法
  3. 高级前端成长训练营|和阿龙一起学前端曝光——走进前端开发世界
  4. 如何通过脚本开发Android
  5. PYPL 4 月排行:Python 最流行,Java 老矣,尚能饭否?
  6. 海贼王经典语录(转)
  7. 初学python找不到的类都到这儿来
  8. 职场健康:久坐不动最伤五部位 简单动作可有效改善
  9. unity 字幕滚动
  10. QT设置默认最大化窗口