JS 教程之 JavaScript 运算符以及流程控制
前面我们已经解读了 JS 中变量以及基本数据类型等基本概念,本文接着来看 JavaScript 中的运算符以及程序流程控制语句,这是一个 JavaScript 程序实现的必要部分。
JS 中的运算符
开始后续的流程控制学习之前,我们需要系统的认识一下 JavaScript 中的运算符(也称为操作符)。
我们先来看一个简单的例子:
1 | > 4 + 5 |
其中,4
,5
被称为 操作数,+
被称之为 运算符(操作符),它们共同构成一个 表达式。
可以看到,JS 中的表达式类似于数学上的数学表达式,由操作数以及操作符(运算符)组合而成。
[1] >>> 特殊概念
–> 优先级 & 结合性
JS 中的运算符,等价于数学中的运算符,也是有优先级,和结合性的概念的。
这也就是说 >>> 当一个表达式中出现多种操作符时,执行的先后顺序不仅要遵守操作符优先级规定,还要受操作符结合性的约束,以便确定是自左向右进行运算?还是自右向左进行运算?
–> 操作数
操作数是指 >>> 运算符进行运算时,所操作(依赖)的数据。
[2] >>>运算符分类
JavaScript 语言中最基本的运算符可归纳为以下 5 大类:
- 赋值运算符
- 算术运算符
- 关系(比较)运算符
- 逻辑运算符
- 位运算符
并且,根据【操作数的数量】又衍生出了:单目运算符、双目运算符、三目运算符 的概念(看到这样的表述不要疑惑)。
JS 运算符详解
这一小节将详细解读上面提到的 5 种 JS 基本运算符用法:
赋值运算符
前面的变量章节部分中提到过 >>> 变量声明时(后),可以使用赋值运算符为变量进行赋值。
赋值运算符就是指,为 变量或常量 指定数值(赋值) 的符号。使用很简单,其语法格式如下所示:
1 | 变量名称 = 值(或表达式) |
它是一个双目运算符。其左边的操作数必须是变量,不能是常量值或表达式;右侧可以为字面值,或表达式。
需要注意的是 >>> 不要将赋值运算符与相等运算符 “==” 混淆。
示例代码如下:
1 | > var i = 1; |
事实上,JS 中还有一种 扩展赋值运算符,它是由其它基本运算符和赋值运算符结合而成。例如算术赋值运算符(
+=
&&-=
&&*=
等),以及位赋值运算符(<<=
&&>>=
等)。通常情况下,只要能使用扩展后的赋值运算符,都推荐使用这种赋值运算符。关于扩展赋值运算符的使用,将在其结合运算符中进行说明。
算术运算符
算术运算符的功能是 >>> 对变量与/或字面量(变量与变量、变量与字面量、字面量与字面量)进行算术运算。
JS 中支持如下的算术运算:
运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | -4 | -4 |
+ | 加法运算 | 5 + 5 | 10 |
- | 减法运算 | 10 - 5 | 5 |
* | 乘法运算 | 5 * 2 | 10 |
/ | 除法运算 | 10 / 3 | 3.333 |
% | 取模(余)运算 | 10 % 3 | 1 |
++ | 自增运算 | a = 2; a++ | 3 |
-- |
自减运算 | a = 10; a-- |
9 |
这里为了方便记忆,特将算术运算分为三类:
- 基本算术运算符:+(加) -(减) *(乘) /(除)%(取模/取余);
- 算术赋值运算符:+=(加法赋值)-=(减法赋值)*=(乘法赋值)/=(除法赋值)%=(取模赋值);
- 算术单目运算符:+(正) -(负) ++(自增)
--
(自减)。
[1] >>> 基本算术运算符
JS 算术运算符中,最基本的算术运算就是:
1 | +(加) -(减) *(乘) /(除)%(取模/取余) |
上述算术运算,和我们平常接触的数学运算具有相同的含义。
加法运算】示例代码如下 >>>
1 | > var aNum = 21; |
当 +
用于数值(Number)类型时表示加法运算;但是当 +
用于字符串类型时表示连接运算(连接运算符),请参照 JavaScript 中的原始 String 类型中的说明。
+
除了用作加法运算符之外,还可以作为正数(正号)的标志(例如:+2
),一般缺省。
减法运算】示例代码如下 >>>
1 | > var aNum = 21, bNum = 10; |
-
除了可以用作减法运算之外,还可以用作求负(负号)运算(正数变负数,负数变正数),即取相反数。
乘法运算】示例代码如下 >>>
1 | > var aNum = 21, bNum = 10; |
需要注意的是,JS 中 *
仅用于数值相乘;而有些编程语言中,*
还用于进行序列(字符串)的重复运算,用于将某个序列复制几份并连接起来。
除法运算】示例代码如下 >>>
1 | > var aNum = 21, bNum = 10; |
需要注意的是,JS 进行除法运算时,除数为 0
时不会产生错误(ZeroDivisionError
),而是输出 Infinity
(正无穷大)。
取模(取余)运算】示例代码如下 >>>
1 | > var aNum = 21, bNum = 10; |
[2] >>> 算术赋值运算符
算术赋值运算符只是一种(赋值和算术运算符结合的)简写形式,一般用于变量自身的变化。
上述的每一种基本算术运算符,都有一种对应的和赋值符结合的简写形式:
运 算 符 | 名 称 | 例 子 | 等价于 |
---|---|---|---|
+= | 加法赋值 | a += b + 3 | a = a + b + 3 |
-= | 减法赋值 | a -= b | a = a - b |
*= |
乘法赋值 | a *= b |
a = a*b |
/= | 除法赋值 | a /= b | a = a/b |
[3] >>> 算术单目运算符
算术操作符中,单目运算符有 4 个,分别表示:+(正) -(负) ++(自增) --
(自减)。
其中,+
(正)&& -
(负)较为简单,就是数学上的含义,不做过多说明。下面重点来看自增、自减的使用。
自增 && 自减 >>> 使用原则:
- 自增/自减只能作用于变量,不允许对字面量、表达式等进行操作;
- 自增/自减运算作用于变量自身加/减
1
,放在操作数的 前面或后面 都是允许的。
3.1 –> 自增 & 自减
i++(自增)i--
(自减):在变量 i 原来的基础上,增加 1
或者减少 1
。
1 | // 自增: |
3.2 –> 前后置的区别
以 ++(自增)为例,--
同理。
1 | > var i = 4; |
具体示例代码如下:
1 | > var i = 5; |
思考一下:下面的 j
是 多少?
1 | > var i = 1; |
关系运算符
关系操作符(relational operators)也可以称为:“比较操作符”,用来比较判断两个变量或字面量的大小关系。
关系运算的结果都是 Boolean 型的。当操作符对应的大小关系成立时,运算结果是 true,否则是 false。
JS 中支持的比较操作符列表如下:
运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
== | 等于,如果 == 两边的值相等,则返回 True;否则返回 False | 4 == 4 | true |
!= | 不相等 (等价于数学中的 ≠),如果 != 两边的值不相等,则返回 True;否则返回 False | 4 != “4” | false |
=== | 等值等型,如果 === 两边的操作数的值以及数据类型都相同,则返回 True;有一个不同则返回 False | 4 == “4” | false |
!== | 不等值或不等型,如果 !== 两边的操作数的值以及数据类型至少有一个不同,则返回 True;否则返回 False | 4 !== “4” | true |
< | 小于,如果 < 前面的值小于后面的值,则返回 True,否则返回 False | 4 < 3 | false |
> | 大于,如果 > 前面的值大于后面的值,则返回 True,否则返回 False | 4 > 3 | true |
<= | 小于等于(等价于数学中的 ≤),如果 <= 前面的值小于或者等于后面的值,则返回 True,否则返回 False | 4 <= 3 | false |
>= | 大于等于(等价于数学中的 ≥),如果 >= 前面的值大于或者等于后面的值,则返回 True,否则返回 False | 4 >= 3 | true |
这里为了方便记忆,特将关系运算分为三类:
- 大小关系检测:<(小于) <=(小于等于) >(大于) >=(大于等于);
- 等值关系检测:==(等于) !=(不相等);
- 相同关系检测:===(等值等型) !==(不等值或不等型)。
[1] >>> 大小关系检测
大小关系检测时,操作数的比较规则:
- 数值与数值比较 >>> 直接比较它们的代数值;
- 仅一个操作数是数值 >>> 将另一个操作数转化为数值后,比较它们的代数值;
- 字符串与字符串比较 >>> 逐字符比较它们的 Unicode 数值;
- 字符串与非数值比较 >>> 将非数值操作数转化为字符串后,进行比较;
- 只要与 NaN 比较 >>> 均返回 false;
- 操作数既非数值也非字符串 >>> 转化为数值或字符串后进行比较;
- 操作数无法被转化为数值或字符串 >>> 均返回 false。
关于操作数的类型转化,你可以参见博文系列中的 JS 中数据类型转换章节。
[2] >>> 等值关系检测
等值关系检测时,操作数的比较规则:
- 数值与/或字符串比较规则同上;
- null == undefined(两者相等),比较前不进行任何转换(相等比较中,null && undefined 允许被转换为其他类型的值。);
- NaN 与任何值都不相等,包括其本身(即:
NaN != NaN
); - 操作数都是对象时,则比较引用地址,引用地址相同,则相等;否则不等。
特殊操作数相等比较实例代码如下:
1 | console.log("1" == 1); // 返回 true |
[3] >>> 相同关系检测
相同关系检测时,操作数的比较规则:
- 值类型间比较 >>> 数据类型相同且数值也相等,才相同;
- 值类型与引用类型比较 >>> 肯定不相同;
- 引用类型间比较 >>> 比较引用地址,引用地址相同,则相同。
特殊操作数相等比较实例代码如下:
1 | console.log(null === undefined); // 返回 false |
逻辑运算符
逻辑运算又称为 布尔代数运算,就是布尔值的运算。JS 中支持的逻辑运算符如下:
a && b
:等价于数学中的 “且”,a 和 b 两个表达式都真为真,有假即假;a || b
:等价于数学中的 “或”,a 和 b 两个表达式有真即真,都假为假;!a
:等价于数学中的 “非”(相当于对 a 取反),如果 a 为真,那么 !a 的结果为假;如果 a 为假,那么 !a 的结果为真。
[1] >>> 短路逻辑特性
短路逻辑概念的引入,是为了优化逻辑表达式的计算方式,从而提高程序效率(实际编程中,应优先考虑使用短路逻辑)。
于是,编程语言设计中对逻辑运算符又进一步细分:
- “且/与” >>> 逻辑与(&) 和 短路与(&&);
- “或” >>> 逻辑或(|) 和 短路或(||)。
对于 短路与(&&)>>> 若第一个表达式是 false,后续的就不进行运算了(有假即假);短路或(||)>>> 若第一个表达式是 true,后续的就不进行运算了(有真即真)。而对于逻辑与(&)和 逻辑或(|)所有表达式均需要计算(效率较低)。
需要注意的是,JS 中的逻辑运算符就是优化计算的短路与(&&)和 短路或(||),不支持另外单独的的逻辑与、或运算符。
[2] >>> 操作关系表达式
由于关系表达式的返回结果都是 Boolean 型的,故:
一般情况下,逻辑运算符会把多个 关系表达式(返回布尔值) 组合成一个逻辑表达式,以判断整个逻辑表达式是否成立,返回的结果是 true 或 false。
1 | > var ageNum = 23; |
[3] >>> 更一般的表达式
前面在介绍原始 Boolean 类型转换时,提到过 布尔值(true && false)可以直接参与逻辑表达式运算。且:
1 | // 逻辑表达式中以下值会被认为是 False: |
也就是说,逻辑运算符可以用来操作任何类型的表达式,不管表达式返回是不是 Boolean 类型的。
[4] >>> 逻辑运算本质
并且,通过逻辑运算的结果也不一定是 Boolean 类型,它也可以是任意类型。
对于 短路与(&&),两边的值都为假时最终结果才为假,有假即假。所以 JS 按照下面的规则执行短路与运算:
- 如果左边表达式的值可转换为假(false),那么就不用计算右边表达式的值了(不管右边表达式的值是什么,都不会影响最终结果,为假),此时会返回左边表达式的值;
- 如果左边表达式的值可转换为真(true),那么最终值是不能确定的,短路与(&&)会继续计算右边表达式的值,并返回右边表达式的值。
对于 短路或(||),情况是类似的,两边的值都为假时最终结果才为假,有真即真。所以 JS 按照下面的规则执行短路与运算:
- 如果左边表达式的值可转换为真(true),那么就不用计算右边表达式的值了(不管右边表达式的值是什么,都不会影响最终结果,为真),此时会返回左边表达式的值;
- 如果左边表达式的值可转换为假(false),那么最终值是不能确定的,短路或(||)会继续计算右边表达式的值,并返回右边表达式的值。
使用代码验证上面的结论:
1 | // 逻辑表达式中以下值会被认为是 False: |
运行看一下:
1 | ----False and xxx----- |
[5] >>> 取反(!)
真变为假,假变为真。示例代码如下:
1 | > var isTrue = true; |
位运算符
编程语言中的位运算(bitwise operators),表示 按 数值 在内存中的每个二进制位(bit)进行计算,也称为 按位运算。
也就是说,JS 中可以直接对 数值类型数据 的二进制位进行操作,其操作数和运算结果都是数值型值。
JS 中支持的位运算操作符列表如下:
运算符 | 描述 | 示例 |
---|---|---|
& | 按位与:参与运算的两个数值,如果对应的二进制位都为 1,则该二进制位的结果为 1;否则为 0 | 5 & 1 等同于 0101 & 0001,结果为 0001,十进制结果为 1 |
| |
按位或:参与运算的两个数值,如果对应的二进制位至少有一个为 1,则该二进制位的结果为 1;否则为 0 | 5 | 1 等同于 0101 | 0001 ,结果为 0101,十进制结果为 5 |
^ | 按位异或:参与运算的两个数值,如果对应的二进制位互异时,则该二进制位的结果为 1;相同结果为 0 | 5 ^ 1 等同于 0101 ^ 0001,结果为 0100,十进制结果为 4 |
~ | 按位非:对某个数值的所有二进制位按位取反,即 1 转换为 0;0 转换为 1 | ~5 等同于 ~0101,结果为 1010,十进制结果为 -6 |
<< | 按位左移:把 “<<” 左边的操作数各二进位全部左移若干位,”<<” 右边的数用来指定移动的位数;高位丢弃,低位补 0 | 5 << 1 等同于 0101 << 1,结果为 1010,十进制结果为 10 |
>> | 按位右移(有符号右移):把 “>>” 左边的操作数的各二进位全部右移若干位,”>>” 右边的数指定移动的位数;拷贝最左侧的符号位来填充左侧 | 5 >> 1 等同于 0101 >> 1,结果为 0010,十进制结果为 2 |
>>> | 按位右移零(无符号右移):把 “>>>” 左边的操作数的各二进位全部右移若干位,”>>>” 右边的数指定移动的位数;最左侧补 0 | 5 >>> 1 等同于 0101 >>> 1,结果为 0010,十进制结果为 2 |
这里为了方便记忆,特将位运算分为三类:
- 位逻辑运算符:&(按位与)、|(按位或)、~(按位非)和 ^(按位异或)
- 位移运算符:<<(按位左移)、>>(有符号按位右移)、>>>(无符号按位右移)
- 位赋值运算符:&=(按位与赋值)、|=(按位或赋值)、^=(按位异或赋值)、<<=(按位左移赋值)、>>=(有符号按位右移赋值)以及 >>>=(无符号按位右移赋值)。
[1] >>> 位逻辑运算符
三目(条件)运算符
其它运算符
JS 教程之 JavaScript 运算符以及流程控制
https://www.orangeshare.cn/2019/02/05/js-jiao-cheng-zhi-yun-suan-fu-yi-ji-liu-cheng-kong-zhi/
install_url
to use ShareThis. Please set it in _config.yml
.