怎么分析一个网站/html友情链接代码
LHS和RHS
之前我们先来回忆一下最简单的赋值操作!
var test=100; console.log(test);
以上代码的意思简单我们理解为把右边
的值
赋值给左边
的test变量
,然后输出打印结果。
可是我们要是深入理解你就会发现在这个过程当中,还发生了一些其他的事情
而这些事情就是今天我们要说的LHS和RHS
就比如之前那段代码:
var test=100;
JS
会将其看成两句声明:var test
和 test=100
弄成两个部分: 编译
和代码执行
var test
这个部分也就是定义声明
的时候就开始进行编译(编译器)
test=100
而后面这一段赋值声明
会留在原地等待代码执行(引擎)
那么JS
中的变量赋值操作
会被拆分执行为两个动作:
-
JS编译器
会在当前作用域
中声明这个变量
,当然是这个变量
不存在的情况下! -
然后在运行代码时,
JS引擎
会在作用域
中查找
这个变量
,如果能找到就会对它进行一些操作,例如:赋值操作
而以上这两部的操作又间接引出LHS和RHS
的概念!
所以这里的JS编译
又与传统的编译语言
是不同的!
LHS与RHS基本概念
LHS 全称为: Left-hand Side(左侧引用)
LHS
其实就是赋值操作
的左侧
查询,LHS查询
试图找到变量
的容器本身,从而对其赋值!
注意:
=操作符
或调用函数
时传入参数的操作都会导致赋值操作!
小结
通常情况下,如果查找的目的是对变量
进行赋值,那么就会使用LHS查询 也就是当变量
出现在赋值操作
的左侧
RHS 全称为: Right-hand Side(右侧引用)
RHS
其实就是赋值操作
的右侧
查询,可以理解为需要获取到某值
小结
通常情况下,如果查找的目的是获取变量或函数
的值,就会使用RHS查询, 也就是当变量
出现在赋值操作
的右侧
总的来说LHS和RHS
通常是指等号赋值运算
的时候,左右边的引用!
可能这样说对于理解LHS和RHS
还是比较抽象
,我们要用一个案例来解释一下!
举个梨子
console.log(test);
按照LHS与RHS
的查找规范, 这段代码就是一个所谓的RHS右侧引用
因为这里test变量
,我们并没有对其进行赋值操作,而只是想在作用域
当中查找这个变量
并取得值,然后输出打印,所以执行的就是RHS
test = 100;
而这段代码当中 按照LHS与RHS
的查找规范, 就是一个LHS左侧引用
因为此时JS
并不关心当前的值是什么, 只是想要给当前这个赋值操作
找到一个目标容器!
我们再看一个案例, 大家可以猜猜看以下代码当中有多少个LHS查询
又有多少RHS查询
?
代码如下
function foo(num) { console.log(num); }foo(100);
分析
-
首先
function foo(num)
这里就存在一个LHS查询
因为100
赋值给了num形参
对吧,也就相当于num=100
,那么就会在这个函数作用域当中先找出num
这个变量容器
! -
而
foo(100)
本身就是在求返回值
的操作, 在作用域当中就会进行RHS查找
这个foo(100)函数
是否存在, 并没有对其进行赋值操作, 所以这里很明显就是一个RHS查找
-
最后
console.log(num)
这里其实又是一个RHS查询
, 因为在这行代码中,我们只有一个变量num
被使用,因此在console.log(num)
中只有一个RHS查询
,在作用域中查找, 用于获取num
的值!
所以正确答案是以上代码当中存在1个LHS查询
, 2个RHS查询
所以通过上面的案例最后我们可以把LHS与RHS
简单的理解为以下概念:
赋值操作的目标是谁,那么就是LHS(左侧引用查找),
谁是赋值操作的源头,则就是RHS(右侧引用查找)
面试题: 请找出以下代码当中,所有的LHS和所有的RHS
function test(num) { var num2 = num; return num + num2; } var num = test(100);
代码分析
包含LHS的代码
-
var num = test(100)
这一段代码很显然是一个LHS
,因为num
在赋值运算的左边
,也就是赋值操作的目标
,所以要对num变量
进行LHS查询
, 那么这里的查询
过程就是由作用域
(词法作用域)进行配合查找的! -
function test(num)
的形参num
在调用test(100)
时,将实参100赋值给了形参num
,也就是num=100
,因为形参num
在赋值运算的左边
,也就是赋值操作的目标
,所以要对形参num
进行LHS查询
-
var num2 = num
这一段代码也是一个LHS
,因为num2
在赋值运算的左边
,也就是赋值操作的目标
,所以要对num2
进行LHS查询
包含RHS的代码
-
var num = test(100)
这段代码虽然有LHS查询
但同时也有RHS
原因之前其实我们也说过,可以把这段代码分成两个部分来看,其中就有test(100)
调用这部分,而这里恰恰是要求得一个结果,需要知道test(100)
的值是多少 那么根据谁是赋值操作的源头
是谁则就是RHS
,从而获取test(100)
的返回值 -
var num2 = num
也跟上面同理虽然有LHS查询
但同时也有RHS
,也就是其中也有num
这个变量
在赋值运算符右边
, 此时需要知道num
的值 那么根据谁是赋值操作的源头
是谁则就是RHS
-
return num + num2
这里我们按照(词法作用域查找)
思维来说需要知道num
和num2
的值, 也就是说只是想查找这两个变量,
并取得它们的值,然后才是进行求和
操作, 所以这里就是RHS查找
, 也就是需要分别对num 和num2
都进行RHS查询
那么根据上面的案例当中,要看出
左侧
和右侧
并不一定意味这就是=号
的左侧和右侧,赋值操作还有其他几种形式
小结
如果查找的目的是对变量进行赋值,那么就会使用LHS查询 如果目的是获取变量的值,就会使用RHS查询
LHS与RHS查找规则
从之前的案例当中,不管是LHS
还是RHS
都会在当前执行的作用域
中开始查找变量
LHS
在查找的时候,是把右边
的值
赋值给左边
的变量
那么就会对左边
的变量
进行当前作用域
中的LHS查询
,来判断是否声明过!
RHS
在查找的时候,是先看谁是赋值操作的源头
, 然后在这个基础之上进行当前作用域
中的RHS查询
,简单点说也就是在当前作用域
中查找右边
的变量
或者函数表达式
来判断是否已经声明过!
那么LHS和RHS
在当前作用域
当中如果没有找到所需的标识符
就会根据作用域链
向上一级作用域
继续查找该标识符
,以此类推这样每次上升一层作用域
去查找, 最后到达全局作用域
就会停止,这也是我们之前讲过的作用域链
!
我们可以回顾一下之前的作用域链
如图
LHS
和RHS
都会在当前执行代码的所在环境
进行查找, 如果没有找到,才往上一层查找 以此类推, 一旦抵达顶层全局作用域
之后,可能找到了你所需的变量
,也可能没找到,但无论如何查找过程都将停止!
结合(作用域+编译器+JS引擎)来理解LHS和RHS
我们用一段代码来说明:
var test = 100;
分析
JS引擎
会认为这里有两个完全不同的声明
一个由编译器
在编译时处理也就是var test
另一个则由JS引擎
在运行时处理,也就是test = 100
当编译器
遇到var test
会向当前作用域
询问是否已经存在这个变量
, 如果有就交给编译器
继续进行编译赋值, 否则它会要求作用域
在当前作用域
的中声明一个新的变量test
然后JS引擎
在运行代码
的时候,会首先询问作用域
,在当前的作用域
中是否存在一个叫作test
的变量
, 如果有,JS引擎
就会使用这个变量
, 如果没有JS引擎
会继续根据作用域链
查找该变量
如果JS引擎
最终找到了test变量
,就会将100赋值给它, 否则JS引擎
就会抛出一个异常!
LHS与RHS异常问题
当RHS查询当前作用域
中如果找不到变量
,引擎会抛出ReferenceError错误
例如: 直接在整个作用域
当中打印输出
一个没有定义声明
的变量或函数
就会报ReferenceError错误
如图
例如:
代码如下
function foo(num) { console.log(num + data); data = num;}foo( 100);
以上的代码当中进行了RHS
但无法查找到, 因为作用域
是往上查找的,这里也很明显是找不到的!
如图
函数也是一样, 在调用一个完全没有声明
的函数
时也会抛出ReferenceError错误
就比如说如下代码:
test();
如图
所以在作用域
中直接调用一个没有定义的test()函数
直接在整个作用域
进行了RHS
查找也没有查到
自然会报ReferenceError错误
但是如果RHS在作用域
中查找到变量
,但是进行了不规范的操作, 比如: 在末尾加了个()
简单点说就是试图对一个非函数类型
的值/变量
进行函数调用
那么JS引擎
会抛出另一种异常
叫做 TypeError(类型异常)
如图
还有就是如果RHS在作用域
中查找到变量
, 但是引用了null
和 undefined
类型的值中的属性,也会报一个TypeError(类型异常)
的错误!
知识点复习
在 JS 中,null 和 undefined 是特殊的值,用于表示变量或属性不存在或没有值。如果你引用 null 或 undefined 类型的值中的属性,意味着你尝试访问一个不存在的属性或者一个没有被赋值的变量。具体而言,如果你尝试在一个 null 或 undefined 类型的值中访问一个属性,JS引擎会抛出一个类型错误(TypeError),提示你不能在 null 或 undefined 上访问属性。
例如,以下代码会抛出TypeError(类型异常)
!
var obj=null;obj.username;
如图
所以这里总结以下:
ReferenceError 是作用域
查找失败,也就是说找不到这个变量或者函数
才抛出来的
而TypeError则代表作用域
查找成功了, 但是对结果
的操作是非法
或不合理
的!
当JS引擎
执行LHS查询时,如果在所有作用域
中找不到目标变量
,就会在全局作用域
中创建一个与该变量名
相同的全局变量,并将其返回给JS引擎
,前提是在非严格模式下
这也正好呼应了我们前面所讲解的隐式全局变量的真正含义!
代码分析以下函数当中的a = 100其实是一个LHS,但是变量a并没有在函数块当中进行声明就直接赋值了,那么没声明的变量正常情况下,作用域中是找不到的那么LHS则会在"全局作用域"中创建一个与该"变量"名相同的"全局变量a"
如图
我们再看一段代码
function foo(a){ num = a; //num = 100}foo(100);
分析
上面的代码执行的LHS查询
,在非严格模式
下,JS引擎
直到在全局作用域
中都没有找到num
这个变量,所以它就在全局作用域中
声明了一个变量num
当然也对变量a
进行一次RHS查询
以获得变量a
的值, 所以此时结果不会报错, 并且num
也被赋值为100
我们也可以使用Chrome
调试工具当中的Sources
中断点
来查看全局作用域
当中是否真的存在这个num变量
,果不其然,我们在global
中找到了这个num变量
如图
但是如果是严格模式
下会ReferenceError的错误
代码如下:
"use strict";function test(){ a=100;}test();console.log(a);
如图
也就是说在严格模式下,LHS查询
是无法帮助我们建立隐式全局变量
的
LHS与RHS的区别
其实我们在熟悉了LHS和RHS
抛出的异常问题之后,就会明白它们彼此的区别在什么地方了!
RHS查询
在所有嵌套
的作用域
中找不到所需的变量或函数
,引擎就会抛出ReferenceError
异常
但是要注意的是,如果RHS查询
找到了一个变量
,但是对这个变量
的值进行不合理的操作, 例如: 使用null
或者undefnied
类型的属性,这种违规操作, JS引擎
会抛出TypeError异常
LHS查询
相比之下,非严格模式
的情况下 执行LHS查询
时,如果在顶层作用域
也无法找到目标变量
,那么全局作用域
会创建一个具有该名称的隐式全局变量
,并将其返回给JS引擎
, 当然如果是在严格模式
下,LHS查询
找不到目标变量
时, 依旧会抛出ReferenceError异常
总结
所以区分LHS和RHS
很重要的依据就是最终 查询在作用域链
中找不到需要的变量
或函数
会抛出什么!
而LHS和RHS
都会在当前执行作用域
中开始查询,当前没找到,就会根据作用域链
向上级作用域
继续查找目标标识符
不成功的RHS
会导致抛出ReferenceError异常
不成功的LHS
会自动隐式
在全局作用域
中创建一个同名的全局变量
严格模式
下也会抛出ReferenceError
异常
作用域与LHS和RHS之间的关系
之前我们学过作用域
是JS引擎
用来管理如何在当前作用域
以及嵌套的子作用域
中根据标识符
名称进行变量
查找的一套规则
如果查找的目的是对变量进行赋值
,那么就会使用LHS查询
如果目的是获取变量的值,就会使用RHS查询
小提示:
要注意一点: 如果代码中引用了类似于foo.bar.baz
,那么词法作用域
查找只会试图查找foo标识符
,找到这个变量
后,再根据对象属性访问
规则会分别接管, 并对bar
和baz
属性的访问!
相关文章:

JavaScript中的LHS和RHS
LHS和RHS之前我们先来回忆一下最简单的赋值操作! var test100; console.log(test); 以上代码的意思简单我们理解为把右边的值赋值给左边的test变量,然后输出打印结果。 可是我们要是深入理解你就会发现在这个过程当中,还发生了一些其他的事情 而这些事情就是今天…...

appium 实战问题 播放视频时无法定位到元素
背景 在做UI自动化时,有播放详情页的用例,但是发现视频在播放的时候无法定位到元素或者很慢,了解到appium在动态的页面实时获取布局元素导致定位变慢。所以只能将视频暂停在操作元素,点击到暂停按钮又是个问题,通过ad…...

鸿蒙‘ohpm‘ 不是内部或外部命令,也不是可运行的程序-解决方案
🔥 博客主页: 小韩本韩! ❤️ 感谢大家点赞👍收藏⭐评论✍️ 在鸿蒙的DevEco Studio的终端下输入 ohpm -v 或者 你需要下载第三方ohpm包的时候提示‘ohpm‘ 不是内部或外部命令,也不是可运行的程序- 主要是因为我们…...

方法引用 异常 file
目录 一.方法引用 1.方法引用概述 2.引用静态方法 3.引用成员方法 i.引用其他成员方法 ii.引用本类成员方法 iii.引用父类成员方法 4.引用构造方法 5.其他调用方式 i.使用类名引用成员方法 ii.引用数组的构造方法 二、异常 1.异常的作用 2.异常的处理方式 i.JVM…...

比较(六)利用python绘制径向柱图
比较(六)利用python绘制径向柱图 径向柱图(Circular Barplot)简介 径向柱图基于同心圆网格来绘制条形图,虽然不如普通条形图表达准确,但却有抓人眼球的效果。其衍生的南丁格尔玫瑰图则广为人知。 快速绘制…...

为什么需要重写equals和如何重写equals
首先先看Java中的 ,比较的两个对象的地址值。 如果是基本数据类型,那么就是比较的是值。 如果是引用数据类型,比较的就是地址. object类中的equals方法也是用的; 所以要比较两个对象的大小,去调用默认的equals方法…...

C#字符串操作:判断一个字符串是否存在于另一个字符串按特定字符分割后的子字符串中的几种方法
要判断一个字符串是否存在于另一个字符串按特定字符分割后的子字符串中,可以使用以下几种方法: 方法一:使用Split和Array.Exists 你可以使用 Split 方法将字符串分割成子字符串数组,然后使用 Exists方法检查目标字符串是否在数组…...

Hi3861 OpenHarmony嵌入式应用入门--MQTT
MQTT 是机器对机器(M2M)/物联网(IoT)连接协议。它被设计为一个极其轻量级的发布/订阅消息传输 协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用,是专为受限设备和低带宽、 高延迟或不可靠的网络而设计。这些原则也使该协议成为新兴的“机器…...

[22] Opencv_CUDA应用之 使用背景相减法进行对象跟踪
Opencv_CUDA应用之 使用背景相减法进行对象跟踪 背景相减法是在一系列视频帧中将前景对象从背景中分离出来的过程,它广泛应用于对象检测和跟踪应用中去除背景 背景相减法分四步进行:图像预处理 -> 背景建模 -> 检测前景 -> 数据验证 预处理去除噪声背景建模,以便与…...

Maven在Windows中的配置方法
本文介绍在Windows电脑中,下载、配置Maven工具的详细方法。 Maven是一个广泛使用的项目管理工具,主要针对Java项目,但也可以用于其他类型的项目;其由Apache软件基金会维护,旨在简化和标准化项目构建过程,依…...

一、redis-万字长文读懂redis
高性能分布式缓存Redis `第一篇章`1.1缓存发展史&缓存分类1.1.1 大型网站中缓存的使用带来的问题1.1.2 常见缓存的分类及对比与memcache对比1.2 数据类型选择&应用场景1.2.1 string1.2.2 hash1.2.3 链表1.2.4 set1.2.5 sortedset有序集合类型1.2.6 总结1.3 Redis高级应…...

搞清楚[继承],易如反掌
穷不失义,达不离道。——孔丘《论语》 继承 1、简单理解2、继承2、1、继承的概念2、2、继承定义2、3、基类和派生类对象赋值转换2、4、继承中的作用域2、5、派生类默认成员函数2、6、继承中的特点2、6、1、友元2、6、2、静态成员2、6、3、菱形继承及菱形虚拟继承 3、…...

Perl 语言入门学习指南:探索高效脚本编程的奥秘
引言 Perl,全称Practical Extraction and Report Language,是一种功能强大的编程语言,特别擅长于文本处理、报告生成以及系统自动化管理任务。自1987年诞生以来,Perl凭借其灵活性、强大的内置功能库和广泛的社区支持,…...

【HTML】-解决页面内容无法选择、复制问题
目录 1、网页内容无法选中 1.1、问题原因 1.2、解决脚本 1.2.1、开启控制台窗口 1.2.2、执行脚本命令 2、内容复制弹出阻止框 2.2、解决脚本 1、网页内容无法选中 1.1、问题原因 今天在访问某一网站平台,需要将内容进行选择、复制时发现不可使用。 在使用…...

C#中委托与事件
一、委托 在面向对象中,我们可以将任何数据类型作为参数传递给方法,能否将一个方法作为参数传递给另一个方法?C#中通过委托可以实现将方法作为参数进行传递。 1.1概念 委托是一种引用类型,它可以用于封装并传递方法作为参数。委…...

通用后台管理(二)——项目搭建
目录 前言 一、安装vue-cli依赖 1、使用yarn下载vue-cli 2、使用npm下载 3、检查一下是否下载成功 二、创建项目 1、创建项目,my-app是项目名称 2、 这里选择vue 2,蓝色表示选中的。 3、启动项目 三、下载项目依赖 四、配置项目 1、修改esli…...

多模态大模型之达摩院通义MPLUG
引言 随着人工智能技术的飞速发展,多模态技术逐渐成为研究的热点。它结合了文本、图像、声音等多种数据类型,为机器理解世界提供了更丰富的视角。本文根据严明老师的达摩院通义MPLUG多模态预训练技术分享,及其在电商等行业的应用实践&#x…...

文章翻译记录
以 PINN 为基础,我们开发了一个框架,用于在不同震源位置和速度模型下进行地震建模。本研究的显著贡献包括: 1. 为了提高网络对不同速度模型的泛化能力,必须将速度变量 vp 作为系统的输入参数。本研究从监督学习中汲取灵感…...

C++ 语法习题(2)
第三讲 循环语句 1.偶数 编写一个程序,输出 1 到 100之间(包括 1 和 100)的全部偶数。 输入格式 无输入。 输出格式 输出全部偶数,每个偶数占一行。 输入样例 No input输出样例 2 4 6 ... 100 参考代码: #include <i…...

使用Gstreamer时遇到WARNING: erroneous pipeline: no element “x264enc“(亲测有效)
WARNING: erroneous pipeline: no element “x264enc” 解决: 我下了gstreamer1.0-plugins-ugly包就解决了 sudo apt install -y gstreamer1.0-plugins-ugly...

SAP 新增移动类型简介
在SAP系统中新增移动类型的过程涉及多个步骤,包括复制现有的移动类型、调整科目设置以及进行必要的测试。以下是新增移动类型的一般步骤和关键点: 复制现有的移动类型: 使用事务代码OMJJ进入移动类型维护界面。 勾选移动类型 这里不填写移动类型,然后直接下…...

SQL性能优化策略
发现问题 通过业务监控发现慢SQL或接口响应延迟。利用性能分析工具定位问题。 定位SQL语句 使用监控工具确定影响性能的SQL语句和表。 SQL查询变慢原因 索引失效:查询未使用索引或索引效率低。多表连接:JOIN操作导致性能下降。查询字段过多…...

代码随想录第四十八天 | 198.打家劫舍, 213.打家劫舍II,337.打家劫舍III
198.打家劫舍 看完想法:这里的偷/不偷,和背包问题中的放/不放感觉是一个道理,所以在dp递推公式中仍旧使用max(dp[i-2] nums[i], dp[i-1]) int rob(vector<int>& nums) {vector<int> dp(nums.size()1,0);if(nums.size()0) …...

C#实用的工具类库
Masuit.Tools Masuit.Tools大都是静态类,加密解密,反射操作,树结构,文件探测,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载…...

首席数据官CDO证书报考指南:方式、流程、适考人群与考试难度
在信息泛滥的今天,数据已转变为企业不可或缺的宝贵资源。 面对海量的信息,如何提炼出价值,为企业带来实质性的收益?首席数据官(CDO)认证的出现正是为了满足这一需求,它不仅是个人专业能力的体现…...

数据库基础复习
数据库简介 关系型数据库:Mysql 、Oracle 、SqlServer.... DB2 达梦 非关系型数据库:Redis 、MongoDB... MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管…...

探索AI大模型(LLM)减少幻觉的三种策略
大型语言模型(LLM)在生成文本方面具有令人瞩目的能力,但在面对陌生概念和查询时,它们有时会输出看似合理却实际错误的信息,这种现象被称为“幻觉”。近期的研究发现,通过策略性微调和情境学习、检索增强等方…...

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第十三章 Linux连接档
i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...

鸿蒙语言基础类库:【@ohos.uri (URI字符串解析)】
URI字符串解析 说明: 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 导入…...

JavaScript---new Map()用法
new Map 创建 Map 对象设置键值对获取值检查键是否存在键值对数量删除键值对清空所有键值对迭代 Map 在JavaScript中,Map 是一个构造函数,用于创建 Map 对象,它可以存储键值对集合。与普通的对象不同,Map 的键可以是任何类型的值&…...