JavaScript新加入的**运算符,哪里有些不一样呢?

news2025/2/23 4:06:09

JavaScript语法(四):新加入的**运算符,哪里有些不一样呢?

上一节课我们已经给你介绍了表达式的一些结构,其中关于赋值表达式,我们讲完了它的左边部分,而留下了它右边部分,那么,我们这节课一起来详细讲解。

在一些通用的计算机语言设计理论中,能够出现在赋值表达式右边的叫做:右值表达式(RightHandSideExpression),而在 JavaScript 标准中,规定了在等号右边表达式叫做条件表达式(ConditionalExpression),不过,在 JavaScript 标准中,从未出现过右值表达式字样。

JavaScript 标准也规定了左值表达式同时都是条件表达式(也就是右值表达式),此外,左值表达式也可以通过跟一定的运算符组合,逐级构成更复杂的结构,直到成为右值表达式。

关于这块的知识,我们有时会看到按照运算符来组织的讲解形式。

这样讲解形式是因为:对运算符来说的“优先级”,如果从我们语法的角度来看,那就是“表达式的结构”。讲“乘法运算的优先级高于加法”,从语法的角度看就是“乘法表达式和加号运算符构成加法表达式”。

对于右值表达式来说,我们可以理解为以左值表达式为最小单位开始构成的,接下来我们就来看看左值表达式是如何一步步构成更为复杂的语法结构。

更新表达式 UpdateExpression

左值表达式搭配 ++ -- 运算符,可以形成更新表达式。

-- a;
++ a;
a --
a ++

更新表达式会改变一个左值表达式的值。分为前后自增,前后自减一共四种。

我们要注意一下,这里在 ES2018 中,跟早期版本有所不同,前后自增自减运算被放到了同一优先级。

一元运算表达式 UnaryExpression

更新表达式搭配一元运算符,可以形成一元运算表达式,我们看下例子:

delete a.b;void a;typeof a;
- a;
~ a;
! a;await a;

它的特点就是一个更新表达式搭配了一个一元运算符。

乘方表达式 ExponentiationExpression

乘方表达式也是由更新表达式构成的。它使用**号。

++i ** 302 ** 30 //正确-2 ** 30 //报错

我们看一下例子,-2 这样的一元运算表达式,是不可以放入乘方表达式的,如果需要表达类似的逻辑,必须加括号。

这里我们需要注意一下结合性,** 运算是右结合的,这跟其它正常的运算符(也就是左结合运算符)都不一样。

我们来看一个例子。

4 ** 3 ** 2

事实上,它是这样被运算的:

4 ** (3 ** 2)

而不是这样被运算的:

(4 ** 3) ** 2

我们来实际在代码中执行一下试试。最终结果是 262144, 而不是 4096。

乘法表达式 MultiplicativeExpression

到这里,我们进入了比较熟悉的表达式类型,乘方表达式可以构成乘法表达式,用乘号或者除号、取余符号连接就可以了,我们看看例子:

x * 2;

乘法表达式有三种运算符:

*
/
%

它们分别表示乘、除和取余。它们的优先级是一样的,所以统一放在乘法运算表达式中。

加法表达式 AdditiveExpression

加法表达式是由乘法表达式用加号或者减号连接构成的。我们看下例子:

a + b * c

加法表达式有加号和减号两种运算符。

+ 
-

这就是我们小学学的加法和减法的意思了。不过要注意,加号还能表示字符串连接,这也比较符合一般的直觉。

移位表达式 ShiftExpression

移位表达式由加法表达式构成,移位是一种位运算,分成三种:

<< 向左移位
>> 向右移位
>>> 无符号向右移位

移位运算把操作数看做二进制表示的整数,然后移动特定位数。所以左移 n 位相当于乘以 2 的 n 次方,右移 n 位相当于除以 2 取整 n 次。

普通移位会保持正负数。无符号移位会把减号视为符号位 1,同时参与移位:

-1 >>> 1

这个会得到 2147483647,也就是 2 的 31 次方,跟负数的二进制表示法相关,这里就不详细讲解了。

在 JavaScript 中,二进制操作整数并不能提高性能,移位运算这里也仅仅作为一种数学运算存在,这些运算存在的意义也仅仅是照顾 C 系语言用户的习惯了。

关系表达式 RelationalExpression

移位表达式可以构成关系表达式,这里的关系表达式就是大于、小于、大于等于、小于等于等运算符号连接,统称为关系运算。

<=
>=
<
>instanceof in

需要注意,这里的 <= 和 >= 关系运算,完全是针对数字的,所以 <= 并不等价于 < 或 ==。例如:

null <= undefined//falsenull == undefined//true

请你务必不要用数学上的定义去理解这些运算符。

相等表达式 EqualityExpression

在语法上,相等表达式是由关系表达式用相等比较运算符(如 ==)连接构成的。所以我们可以像下面这段代码一样使用,而不需要加括号。

a instanceof "object" == true

相等表达式由四种运算符和关系表达式构成,我们来看一下运算符:

  • ==

  • !=

  • ===

  • !==

相等表达式又包含一个 JavaScript 中著名的设计失误,那就是 == 的行为。

一些编程规范甚至要求完全避免使用 == 运算,我觉得这样规定是比较合理的,但是这里我还是尽量解释一下 == 的行为。

虽然标准中写的 == 十分复杂,但是归根结底,类型不同的变量比较时 == 运算只有三条规则:

  • undefined 与 null 相等;

  • 字符串和 bool 都转为数字再比较;

  • 对象转换成 primitive 类型再比较。

这样我们就可以理解一些不太符合直觉的例子了,比如:

false == '0' truetrue == 'true' false[] == 0 true[] == false truenew Boolean('false') == false false

这里不太符合直觉的有两点:

  • 一个是即使字符串与 boolean 比较,也都要转换成数字;

  • 另一个是对象如果转换成了 primitive 类型跟等号另一边类型恰好相同,则不需要转换成数字。

此外,== 的行为也经常跟 if 的行为(转换为 boolean)混淆。总之,我建议,仅在确认 == 发生在 Number 和 String 类型之间时使用,比如:

document.getElementsByTagName('input')[0].value == 100

在这个例子中,等号左边必然是 string,右边的直接量必然是 number,这样使用 == 就没有问题了。

位运算表达式

位运算表达式含有三种:

  • 按位与表达式 BitwiseANDExpression

  • 按位异或表达式 BitwiseXORExpression

  • 按位或表达式 BitwiseORExpression

位运算表达式关系比较紧密,我们这里放到一起来讲。

按位与表达式由按位与运算符(&)连接按位异或表达式构成,按位与表达式把操作数视为二进制整数,然后把两个操作数按位做与运算。

按位异或表达式由按位异或运算符(^)连接按位与表达式构成,按位异或表达式把操作数视为二进制整数,然后把两个操作数按位做异或运算。异或两位相同时得 0,两位不同时得 1。

异或运算有个特征,那就是两次异或运算相当于取消。所以有一个异或运算的小技巧,就是用异或运算来交换两个整数的值。

let a = 102, b = 324;
a = a ^ b;
b = a ^ b;
a = a ^ b;console.log(a, b);

按位或表达式由按位或运算符(|)连接相等表达式构成,按位或表达式把操作数视为二进制整数,然后把两个操作数按位做或运算。

按位或运算常常被用在一种叫做 Bitmask 的技术上。Bitmask 相当于使用一个整数来当做多个布尔型变量,现在已经不太提倡了。不过一些比较老的 API 还是会这样设计,比如我们在 DOM 课程中,提到过的 Iterator API,我们看下例子:

var iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT, null, false);var node;while(node = iterator.nextNode())
{    console.log(node);
}

这里的第二个参数就是使用了 Bitmask 技术,所以必须配合位运算表达式才能方便地传参。

逻辑与表达式和逻辑或表达式

逻辑与表达式由按位或表达式经过逻辑与运算符连接构成,逻辑或表达式则由逻辑与表达式经逻辑或运算符连接构成。

这里需要注意的是,这两种表达式都不会做类型转换,所以尽管是逻辑运算,但是最终的结果可能是其它类型。

比如:

false || 1;

这句将会得到结果 1。

false && undefined;

这句将会得到 undefined。

另外还有一点,就是逻辑表达式具有短路的特性,例如:

true || foo();

这里的 foo 将不会被执行,这种中断后面表达式执行的特性就叫做短路。

条件表达式 ConditionalExpression

条件表达式由逻辑或表达式和条件运算符构成,条件运算符又称三目运算符,它有三个部分,由两个运算符 ? 和 : 配合使用。

condition ? branch1 : branch2

这里需要注意,条件表达式也像逻辑表达式一样,可能忽略后面表达式的计算。这一点跟 C 语言的条件表达式是不一样的。

条件表达式实际上就是 JavaScript 中的右值表达式了 RightHandSideExpression,是可以放到赋值运算后面的表达式。

总结

今天我们讲解了表达式的右边部分,讲到了包括更新表达式、一元运算表达式、乘方表达式、乘法表达式、移位表达式等 14 种表达式。至此为止,我们已经讲全了表达式。你如果有不熟悉的地方,可以随时回头查阅。

留一个小任务,我们试着总结下 JavaScript 中所有的运算符优先级和结合性。例如:

更多相关内容👉:开发者网站--技术前沿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1359724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql: 2006, ‘MySQL server has gone away‘

一、错误问题 这个问题是在迁移数据库、备份还原或数据导入时报错&#xff1a;2006, ‘MySQL server has gone away‘ 二、出现原因 sql操作的时间过长&#xff0c;或者是传送的数据太大(例如使用insert ... values的语句过长&#xff0c; 这种情况可以通过修改max_allowed_pac…

DZ-200系列中间继电器 板后不带底座 DZY-212X DC220V JOSEF约瑟

DZY-200系列中间继电器 系列型号&#xff1a; DZY-201中间继电器 DZY-222中间继电器 DZY-202中间继电器 DZY-203中间继电器 DZY-204中间继电器 DZY-205中间继电器 DZY-206中间继电器 DZY-207中间继电器 DZY-208中间继电器 DZY-209中间继电器 DZY-210中间继电器 DZY-211中间继电…

Linkage Mapper 工具参数详解——Centrality Mapper

【小白一学就会无需其他教程】此文档用于解析使用Linkage Mapper 各输入输出参数详情以及可能的影响&#xff0c;并介绍了如何解释模型输出结果和输出参数&#xff0c;适合刚入手的人。篇幅很长很啰嗦&#xff0c;是因为每个参数都解释的万分细致。 从以下链接中获取内容&…

AI绘画治愈系风景

大家好&#xff0c;分享风景壁纸&#xff0c;缓解心情。 是非成败转头空&#xff0c;青山常在&#xff0c;暖阳不移。 渡人先渡己&#xff0c;选取色彩缤纷故事&#xff0c;运用AI绘画&#xff0c;构建我们平时极少看到的场景&#xff0c;又有冲突和破碎感&#xff0c;融在一…

Spring Boot 整合 Knife4j(快速上手)

关于 Knife4j 官方文档&#xff1a;https://doc.xiaominfo.com/ Knife4j是一个基于Swagger的API文档生成工具&#xff0c;它提供了一种方便的方式来为Spring Boot项目生成在线API文档。Knife4j的特点包括&#xff1a; 自动化生成&#xff1a;通过Swagger注解&#xff0c;Kn…

Jmeter 性能 —— 电商系统TPS计算

1、怎么计算得出TPS指标 ①第一个通过运维那边给的生产数据&#xff0c;看一下生产进件有多少&#xff0c;计算得来的&#xff0c;如果没有生产数据&#xff0c;或者不过就看如下的方法 ②第二个就是根据最近一个月的实际访问数据&#xff0c;比如每天调用了多少个接口&#…

算法基础之合并果子

合并果子 核心思想&#xff1a; 贪心 Huffman树(算法): 每次将两个最小的堆合并 然后不断向上合并 #include<iostream>#include<algorithm>#include<queue> //用小根堆实现找最小堆using namespace std;int main(){int n;cin>>n;priority_queue&l…

从零学Java - 面向对象 abstract

面向对象 abstract 文章目录 面向对象 abstract1.什么是抽象?1.1 生活中的抽象 2.抽象类2.1 不该被创建对象的类2.2 抽象类的语法2.3 抽象类的作用2.4 抽象类的特点 3.抽象方法3.1 不该被实现的方法3.2 抽象方法的语法3.3 抽象方法的特点 4.总结4.1 抽象类4.2 抽象方法 1.什么…

SpringCloud之Eureka组件工作原理详解

Eureka是一种服务注册与发现组件&#xff0c;最初由Netflix开发并开源出来。它主要用于构建分布式系统中的微服务架构&#xff0c;并提供了服务注册、服务发现、负载均衡等功能。在本文中&#xff0c;我们将详细解释Eureka的工作原理。 一、Eureka概述 Eureka是Netflix开源的一…

QT上位机开发(网络程序界面开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 传统的上位机对接方式还是以232、485、can为主&#xff0c;随着网络的发展&#xff0c;越来越多的设备都是以网络进行通信的。毕竟相比较之前&…

x-cmd pkg | procs - ps 命令的现代化替代品

目录 简介首次用户功能特点类似工具进一步阅读 简介 procs 是用 Rust 编写的 ps 替代品&#xff0c;用于显示有关任务进程的信息 首次用户 使用 x procs 即可自动下载并使用 在终端运行 eval "$(curl https://get.x-cmd.com)" 即可完成 x 命令安装, 详情参考 x-cmd…

vmware安装redhat 7.6 操作系统

vmware安装redhat 7.6 操作系统 1、下载redhat 7.6 操作系统镜像文件2、安装redhat 7.6操作系统3、配置redhat 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载redhat 7.6 操作系统镜像文件 链接: 盘盘 zwzg 文件名&#xff1a;rhel-serv…

nginx 二、配置域名

文章目录 一、配置本地域名查看虚拟机ip修改hosts文件测试域名是否配置成功 二、配置aliyun域名三、实践1.创建html2.配置nginx3.测试服务器内部测试页面测试 总结 docker中启动nginx容器完成如下操作&#xff0c;对于docker安装nginx可以看这篇文章 nginx 一、安装与conf浅析 …

【产品应用】一体化伺服电机在管道检测机器人中的应用

一体化伺服电机在管道检测机器人的应用正日益受到关注。管道检测机器人是一种能够在管道内部进行检测和维护的智能化设备&#xff0c;它可以检测管道的内部结构、泄漏、腐蚀等问题&#xff0c;以确保管道的安全和稳定运行。而一体化伺服电机作为机器人的动力源&#xff0c;对于…

在mybatis中编写SQL时,提示表名和字段名的设置方法

一、在设置中搜索SQL Dialects 二、将Global SQL Dialect和Project SQL Dialect设置为MySQL 三、添加Path&#xff0c;选择当前项目&#xff0c;完成后应用 四、连接要使用的数据库&#xff0c;连接到具体要使用的数据库 五、连接完成后&#xff0c;在xml中编写sql语句就会有…

数据结构:图详解

图的存储方式 邻接矩阵 首先先创建图&#xff0c;这一个我们可以使用邻接矩阵或者邻接链 表来进行存储&#xff0c;我们要实现的无向图的创建&#xff0c;我们先创建 一个矩阵尺寸为n*n&#xff0c;n为图中的节点个数如图所示 可以看出图中有5个结点&#xff0c;那我们创建…

Idea live template

1:打印入参日志的配置 log.info("$methodName$ 方法入参: $argsLog$",$argsJson$); methodName:methodName() argsLog:groovyScript( "def result; def params\"${_1}\".replaceAll([\\\\[|\\\\]|\\\\s], ).split(,).toList(); for(i 0; i <…

HarmonyOS 组件通用属性之位置设置

本文 我们来说 通用属性中的位置设置 主要是针对组件的对齐方式 布局方向 显示位置 做过WEB开发的 对流式布局应该都不陌生 就是 一行放内容 不够放就换行 我们可以先这样写 Entry Component struct Index {build() {Row() {Column() {Stack(){Text("你好")Text(&…

尼康、索尼和佳能各大行业利用先进防伪技术对抗人工智能造假

尼康、索尼集团和佳能正在开发相机技术&#xff0c;将数字签名嵌入图像中&#xff0c;以便将其与日益复杂的假货区分开来。尼康将为摄影记者和其他专业人士提供具有认证技术的无反光镜相机&#xff0c;而索尼计划通过固件更新&#xff0c;在三款专业级无反光镜单反相机中整合数…

梯度、散度、旋度

目录 梯度Gradient —— Scalar -> Vector 散度Divergence —— Vector -> Scalar 旋度Curl —— Vector -> Vector 梯度Gradient —— Scalar -> Vector 即函数在该点处沿着该方向&#xff08;此梯度的方向&#xff09;变化最快&#xff0c;变化率最大&#x…