【javascript】作用域的理解(LHS,RHS查询)

2023-11-15

作用域是什么?

一,理解作用域

任何javascript代码片段在执行前都要进行编译,先看一个例子吧:

// 先思考一下这行代码是如何被编译的?
var a = 33

// 估计大部分人看到这行代码,会说首先声明一个变量a,然后给它赋值33
// 但实际上并没有这么简单

首先要先知道js在解析var a = 33这行代码的时候都有哪些东西参与了。

  1. 引擎:从头到尾负责整个js程序的编译及执行过程
  2. 编译器:负责语法分析及代码生成
  3. 作用域:简单点说就是存储变量的仓库,引擎和编译器通过(LHS,RHS)查询,来查找变量是否存在。暂时可以将LHS和RHS理解为一种查询方式,下边会详细说。

基于上文,事实上编译器会这么处理,继续拿var a = 33来举例子:

var a = 33

/** 
* 1. 编译器会去逐行进行语法分析和代码生成,所以它首先会遇到var a
* 2. 编译器去作用域中查询(LHS),变量a是否存在,如果存在,就继续往下编译,
*   否则就会在作用域中新建一个变量a
* 3. 然后编译器会生成a = 33这行代码并交给引擎去执行,这时候引擎会向作用域发起查询(LHS),
* 询问当前作用域中是否存在变量a,如果不存在,就会向当前作用域的上一级作用域去查找
* (可以理解为当前作用域仓库外边套了一个更大的仓库,在当前仓库找不到,就跑到仓库外边那个更大的仓库去找),也叫作用域链。
* 如果在这条作用域链中还是没找到,那么就会在顶级(最最外边那个仓库)作用域下创建一个a变量,并给它赋值33
* 如果在当前作用域找到了,就会直接将33赋值给a
*/ 

二.LHS和RHS查询

上文中多次提到LHS和RHS查询,那么它俩到底是啥呢?

简单点说,当变量出现在赋值操作的左侧时是LHS查询,非左侧时是RHS查询。也可以将LHS理解成是给谁赋值,RHS理解为赋值操作的源头。

// 举个例子吧
console.log(a)
/**
*这里的a就是一个RHS查询,因为a没有发生任何赋值操作,所以肯定不在赋值操作的左侧,那么就是非左侧,所以它是一个RHS查询。
*然后还有一个console,同上,所以它也是一个RHS查询,回去作用域链中查找console这个对象,查到之后就会调用它的log方法去打印出a
*/

然后再深入思考下,如果通过RHS查询,并且在作用域链中没有找到变量a呢?这时候引擎就会抛出一个ReferenceError错误,表示RHS查询失败,那么如果LHS查询失败呢?

大家先来看看俩例子吧,看完这俩例子可能会对作用域以及作用域链和LHS,RHS查询有更深刻的理解:

// 先来看看下边这个例子
function fn(a) {
  b = a;
}
fn(3);
console.log(b);
/**
*毫无疑问,它打印的是3,然后我们来分析一下过程:
*执行fn函数,引擎想要获取fn的结果,所以对这个函数发起了一次RHS查询
*将实参3赋值给形参a,也就是a = 3,这里的a进行了一次LHS查询
*然后b = a,这里对b进行了一次LHS查询,注意!!!然后问题出现了!!!
*引擎对b进行LHS查询的时候,在当前作用域没找到,所以它就会在上级作用域中去找
*但是在上级作用域中同样没找到,这时候它就会在顶级作用域(就是这里的最外围作用域)中去创建一个变量b
*然后对a进行RHS查询,在作用域中找到a的值之后,赋值给b
*最后打印b,对b发起一次RHS查询,因为之前已经创建过并且给b赋值了,所以可以查询到b的值
*最后对console发起RHS查询并顺利打印出3
*/
// 再来看看下边这个例子
function fn(a) {
  console.log(a + b);
}
fn(3);

/**
 *这时候大家肯定会知道这样会报b is not defined的错,但如果分析一下为什么呢?
 *首先先来看看都发生了几次LHS以及RHS查询:
 *执行fn函数,发生了一次RHS查询,会去当前作用域中查找函数fn,然后找到了
 *接着进行了一次隐式操作,给形参a赋值实参3,也就是a = 3,那么这里就对a进行了一次LHS查询
 *接着执行console.log(a + b)
 *因为log方法想获取a + b的值,所以会对a和b分别进行一次RHS查询,对B进行查询的时候在作用域链中没找到,所以会抛出ReferenceError的错误.
 */

总结

  1. 作用域就相当于一个存储变量的仓库,作用域链就相当于仓库外边又套了一层仓库,如果在当前作用域(也就是当前仓库)没有找到变量的话,那么就会在上级作用于(外层仓库)去找,就这样一层层找,直到顶级作用域。
  2. LHS和RHS,可以这样理解:如果查找的目的是对变量进行赋值,那么就是LHS查询。如果是获取变量的值,那么就是RHS查询
a = 3
//这里就是LHS查询,因为是对a赋值了
console.log(a + b)
//这里就是RHS查询,因为log这个方法想要获取a+b的值.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【javascript】作用域的理解(LHS,RHS查询) 的相关文章

  • 如何在 AngularJS 中使用 $timeout 运行带有参数的函数?

    我的 AngularJS 控制器中有这个函数 看起来像这样 polling interval 1000 var poll function Execution code timeout poll polling interval poll
  • 使用 AJAX 来回发送信息

    使用 post 你可以向服务器发送信息 但是当你需要从服务器接收信息时怎么办呢 信息如何从可以由 php 变量保存的方式变为可以由 javascript 变量保存的方式 反之亦然 这与您的问题更相关 http docs jquery com
  • 使用 HTML5 FileSystem API 将文件写入桌面

    我正在玩一下文件系统API http www html5rocks com en tutorials file filesystem 我发现了很多生成下载链接并让用户以 浏览器方式 下载文件的示例 我想知道两件事 有没有办法将fiddle中
  • 使用shinyjs通过javascript在闪亮的应用程序中操作现有的Leaflet地图

    我有一个闪亮的应用程序 其中包含现有的传单地图 我希望能够在渲染后使用自定义 javascript 通过shinyjs包裹 一个最小的例子如下 app R packages library dplyr library leaflet lib
  • Vue js按钮冻结dom

    我试图在按下按钮时切换包含加载动画的跨度 直到使用 v if 函数完成 但是当我按下按钮时 DOM 冻结并且 span 元素保持不变 直到函数调用结束 如何让 DOM 不冻结并显示加载图标 非阻塞按钮按下可能是一个解决方案 HTML
  • 将字符串转换为变量名。 (JavaScript)

    我确实查看了前面的问题 但它们是针对整数值的 我需要文本值的答案 我在本周早些时候问了一个与此相关的问题 但现在是这样 如下所示 我使 Make x 等于某个字符串值 Acura Honda Toyota 当我将 Make x 传递到函数
  • AttachEvent 或 addEventListener - 存储在哪里?

    在 jQuery 中 如果我这样做 a click function Do something 点击事件存储在 a data events 我可以像这样获取它 jQuery each a data events function i eve
  • 拖放图像上传在服务器上不起作用

    我正在尝试实现拖放图像上传 我在网上找到了一个相当简单的脚本并适合我的使用 在我的本地安装中 文件上传得很好 但在服务器上却不行 从我的调试尝试来看 SERVER HTTP X FILENAME 甚至没有被 php 设置 我尝试了以下方法
  • 从 UnityWebGL jslib 返回字符串

    我想使用 jslib 来获取网址参数 像这样的代码 jslib GetUrl function var s var strUrl window location search var getSearch strUrl split var g
  • 如何混淆或使 JavaScript 文件不可读?

    我的应用程序中有 JavaScript 脚本 其中包含 JavaScript 和 jQuery 函数 所有用户与我的应用程序的交互都是动态的 并且通过 jQuery 传递到应用程序 我意识到 当我在客户端运行我的应用程序时 客户端可以通过查
  • 自动调整元素 (div) 大小以适合水平内容

    我尝试谷歌搜索 但没有得到太多结果 我正在构建一个水平轮播 它在浮动的 LI 中显示图像 我想解决的问题是 每次我向轮播添加缩略图 我是延迟加载 时 我都需要重新计算轮播的宽度 以便所有浮动缩略图很好地并排排列 其一 我宁愿不必在 JS 中
  • 是否可以从 webpack 中的文件名中删除特殊字符?

    长话短说 我的资产文件名中不能包含某些字符 例如连字符 我没有运气通过解析 webpack 文档来弄清楚是否可以使用正则表达式或类似的东西重命名文件 这样我就可以从我无法控制源文件名的 3rd 方包中删除任何连字符 我的超级天真的例子是这样
  • Javascript/DOM:如何删除 DOM 对象的所有事件侦听器?

    只是问题 有没有办法完全删除对象的所有事件 例如一个div 编辑 我添加每div addEventListener click eventReturner false 一个事件 function eventReturner return f
  • Javascript 替换为正则表达式无法正常工作

    我正在尝试使用正则表达式验证名称 正则表达式阻止用户连续输入 2 个空格或点 这是我的代码 function test input var regex A Za z 0 1 s 0 1 input value input value rep
  • 使用重复模式捕获正则表达式

    我试图捕获字符串的所有部分 但我似乎无法正确处理 该字符串具有以下结构 1 22 33 中间有运算符的数字 可以有任意数量的术语 我想要的是 1 22 33 1 22 33 但我得到 1 22 33 22 33 我尝试过各种正则表达式 这是
  • 在64位环境中加载32位进程

    我有以下几个问题 CHM 是 编译的 HTML 文件 我的 CHM 文件有一个启动 32 位应用程序的链接 CHM 文件是用 Javascript 编码的 这在 32 位操作系统环境中运行良好 但这在 64 位操作系统环境中不起作用 原因是
  • 网页执行回发时如何停止在注册表单上?

    我正在做我的最后一年的项目 其中 我在一页上有登录和注册表单 WebForm 当用户点击锚点时Sign Up下拉菜单ddlType 隐藏 和文本框 txtCustName txtEmail and txtConfirmPassword 显示
  • 当 jQuery .remove() 用于删除脚本标签时,它是否会清除加载的 JavaScript?

    正如标题所示 如果我使用以下命令从 DOM 中删除脚本标签 scriptid remove javascript 本身是保留在内存中还是被清除了 或者 我完全误解了浏览器处理 javascript 的方式吗 这是很有可能的 对于那些对我提问
  • ES6解构对象赋值函数参数默认值

    您好 我正在查看在传递函数参数时使用对象解构的示例对象解构演示 https developer mozilla org en US docs Web JavaScript Reference Operators Destructuring
  • 相当于 JavaScript 中 Ruby 的each_cons

    许多语言都曾提出过这个问题 但 javascript 却没有 Ruby 有方法Enumerable each cons https devdocs io ruby 2 5 enumerable method i each cons看起来像这

随机推荐

  • xss绕过,payload全集

    XSS总结 xss分为三种 反射型xss DOM型XSS及存储型XSS 不同类型的XSS的危害不同 有兴趣的可以观看一下csdn上明智讲的关于XSS攻击及原理 https edu csdn net course detail 8585里面的
  • OMG,学它!java培训讲师面试技巧

    基础 JAVA基础 JAVA集合 JAVA多线程并发 网络 数据结构与算法 框架 Spring SpringMVC MyBatis 设计模式 分布式 负载均衡 Zookeeper Redis MQ kafka 微服务 Netty与RPC S
  • Linux常用的四种压缩命令

    文章目录 一 tar命令 二 gzip命令 三 rar命令 四 zip命令 总结 一 tar命令 语法 tar option file 常用参数 c或 create 建立新的备份文件 f lt 备份文件 gt 或 file lt 备份文件
  • Substance与PBR工作流总结

    关于PBR PBR即基于物理的渲染 是一套尝试基于真实世界光照物理模型的渲染技术合集 使用了一种更符合物理学规律的方式来模拟光线 达到更真实的渲染效果 而且可以直接通过物理参数来直观地达到想要的结果 不用通过拙劣的各种参数调整 物理参数一般
  • uni-app crypto-js DES 加解密 ,支持app , h5,小程序

    crypto js DES 加解密 支持app h5 小程序 第一步 npm install crypto js 可以直接下载示例运行 看控制台打印 下载地址 https ext dcloud net cn plugin id 13351
  • Git GitHub入门2:新建Git repository并提交修改

    选择一个文件夹 执行 git init 命令 we initialize an empty git repository in the current directory 要想使用ls 查看列表 需要换成Windows powershell
  • 利用WMI打造完美三无后门(scrcons.exe)

    Welcome 各位ScriptKid 欢迎来到脚本世界 今天忙了一天 比较累 不废话那么多了 切入正题 这个 三无 后门的核心就是WMI中的永久事件消费者ActiveScriptEventConsumer 以下简称ASEC WMI中有许多
  • 微电网日前优化调度 。算例有代码(3)

    个人电气博文传送门 学好电气全靠它 个人电气博文目录 持续更新中 在前文我对问题1 2进行了解答 本文对问题3 进行解答 由于本人非研究调度的 问题3求解阐述自己对比赛论文问题3的见解 问题3 最优日前调度方案二 若考虑蓄电池作用 且微网与
  • camera HSYNC:VSYNC

    HSYNC 行锁存 换行信号VSYNC 祯锁存 换页信号 320 240的屏 每一行需要输入320个脉冲来依次移位 锁存进一行的数据 然后来个HSYNC 脉冲换一行 这样依次输入240行之后换行同时来个VSYNC脉冲把行计数器清零 又重新从
  • MySql基础汇总-DDL DML DQL DCL,存储过程,事务,触发器,函数等

    use testdb 一 数据库操作语言 DDL 数据库定义语言 create drop alter DML 数据库管理语言 insert update delete DQL 数据库查询t usert student 语言 select D
  • upload-labs靶场全通关

    upload labs靶场全通关 pass 1 pass 2 pass 3 pass 4 pass 5 pass 6 pass 7 pass 8 pass 9 pass 10 pass 11 pass 12 pass 13 pass 14
  • linux如何入门

    微信设置水滴昵称 个性中带点萌 1 学习Linux之前先认识Unix l Unix是一个强大的多用户 多任务操作系统 l 于1969年在AT T的贝尔实验室开发 l UNIX的商标权由国际开放标准组织 The Open Group 所拥有
  • js逆向-常见DES加密

    声明 本文仅供参考学习 切勿用于他途 违者后果自负 前言 目标网站 aHR0cHM6Ly9wYXNzcG9ydC5jaGFuZ2hvbmcuY29tL2xvZ2luLmRvP3ZpZXc9dmlwJnNlcnZpY2U9aHR0cDovL2
  • 向上转型和向下转型

    一 概念 向上转型是指将子类的实例赋值给父类类型的变量 向下转型是指将父类的实例赋值给子类类型的变量 二 向上转型 1 向上转型后父类的引用所指向的属性是父类的属性 2 如果子类重写了父类的方法 那么父类引用指向的或者调用的方法是子类的方法
  • 如何使用VuePress开发并部署静态博客网站(附进阶的自定义主题教程)

    VuePress使用教程 前言 作为一个程序员 拥有一个自己的博客网站算得上是家常便饭了 每当我们解决一个问题时 及时总结并记录下来是一个对学习很有帮助的习惯 方便以后遇到同类型的问题时 不用再去百度谷歌找半天 而将这些内容发布在自己的博客
  • php之curl带头部header的post请求

    public function op url http www baidu com test na oh header array Accept Language zh CN x appkey 114816004000028 x apsig
  • 内联函数及其注意事项

    default argument 是编译器记住了default argument 但是运行时还是要两个参数的 编译器看到了原型声明 可以有default argument值 所以编译器替你补上了 建议 不要使用default argumen
  • java上机题编程题

    1 编写程序 用数组实现乘法小九九的存储和输出 提示 采用多个一维数组 public class Multipation public static void main String args TODO Auto generated met
  • Linux一句话精彩问答--

    0001 修改主机名 陈绪 vi etc sysconfig network 修改HOSTNAME一行为 HOSTNAME 主机名 没有这行 那就添加这一行 吧 然后运行命令 hostname 主机名 一般还要修改 etc hosts文件中
  • 【javascript】作用域的理解(LHS,RHS查询)

    作用域是什么 一 理解作用域 任何javascript代码片段在执行前都要进行编译 先看一个例子吧 先思考一下这行代码是如何被编译的 var a 33 估计大部分人看到这行代码 会说首先声明一个变量a 然后给它赋值33 但实际上并没有这么简