||
和&&
与短路运算符
假值:
- false
- null
- undefined
- NaN
- 0(包括+0,-0,0n)
''
空字符串
||(一真则真)
||
先依次进行布尔判定,返回第一个真值,而且不会再进行后面的比较与计算;如果都是假值则返回最后一个值
应用:默认值设置 ||
1 2 3
| let value = possiblyUndefinedVariable || 'default value';
|
&&(一假则假)
先依次进行布尔判定,返回第一个假值,而且不会再进行后面的比较与计算;如果都是真值则返回最后一个值
应用:&&
短路运算代替 if
1 2 3 4 5 6 7 8
| if (condition) { executeFunction(); }
condition && executeFunction();
|
应用:安全的对象属性访问
使用 &&
运算符可以避免在访问嵌套属性时由于中间的对象不存在而抛出的 TypeError。 这就是所谓的”安全的对象属性访问”。(访问不到也不会报错)
1 2 3 4 5 6 7 8
| let value = obj && obj.prop && obj.prop.subProp;
|
?.
Optional Chaining (可选链)
对于上面“安全的对象属性访问”的例子,?.
提供了一种更简洁的方式来安全地访问深层次的对象属性。
1 2 3
| let value = obj?.prop?.subProp || 'default value';
|
??
空值合并运算符
??
类似于 ||
运算符,但只在左边的操作数为 null
或 undefined
时,才会返回右边的操作数。
它比||
更加细化,||
只能看真假,而??
具体到null
或 undefined
。
1 2 3 4
| let value = possiblyZeroOrEmptyString ?? 'default value';
|
算数运算符
+
, -
, *
, /
, %
, **
。
数字运算
纯数字之间正常数学运算,但要注意number
和BigInt
之间不能混合运算,而且BigInt
的运算与number
相同,但除法会省略小数部分。
1 2 3 4 5 6 7 8 9 10 11 12 13
| console.log(3 + 7); console.log(3 - 7); console.log(3 * 7); console.log(3 / 7); console.log(3 % 7); console.log(2 ** 2); console.log(4 + 5n); console.log(3n + 7n); console.log(3n - 7n); console.log(3n * 7n); console.log(7n / 3n); console.log(3n % 7n); console.log(2n ** 2n);
|
特殊字面量参与运算
NaN
与任何值进行算术运算(除了字符串连接),结果都是 NaN
。 NaN
与任何值(包括 NaN
自身)进行比较的结果都是 false
。
1 2 3 4 5 6 7
| console.log(NaN + 3); console.log(NaN - 3); console.log(NaN * 3); console.log(NaN / 3); console.log(NaN % 3); console.log(NaN ** 3); console.log(NaN + '');
|
Infinity
与-Infinity
当超过 JavaScript 数字的最大值时,会产生 Infinity
,当超过最小值时,会产生 -Infinity
。 它们参与的运算,视情况而定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| console.log(Infinity + 3); console.log(Infinity - 3); console.log(Infinity * 3); console.log(Infinity / 3); console.log(Infinity % 3);
onsole.log(-Infinity + 3); console.log(-Infinity - 3); console.log(-Infinity * 3); console.log(-Infinity / 3); console.log(-Infinity % 3);
console.log(3 / Infinity); console.log(3 % Infinity); console.log(3 / -Infinity); console.log(3 % -Infinity);
console.log(Infinity + Infinity); console.log(-Infinity - Infinity) console.log(Infinity - Infinity); console.log(-Infinity - Infinity) console.log(Infinity * Infinity); console.log(Infinity / Infinity); console.log(Infinity % Infinity);
|
undefined
与任何值进行算术运算时,结果都是 NaN。除了字符串连接外
在 JavaScript 中,undefined
隐式转换为以下值:
- 当
undefined
参与数学运算时,会被转换为 NaN
(非数字) 。
- 当
undefined
与字符串拼接时,会被转换为字符串 "undefined"
。
- 当
undefined
与布尔运算时,会被转换为 false
。
- 当
undefined
与对象比较时,通常会被转换为 null
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| console.log(undefined + 3); console.log(undefined - 3); console.log(undefined * 3); console.log(undefined / 3); console.log(undefined % 3); console.log(undefined ** 3);
console.log(undefined + undefined); console.log(undefined - undefined); console.log(undefined * undefined); console.log(undefined / undefined); console.log(undefined % undefined); console.log(undefined ** undefined);
console.log(undefined + null); console.log(undefined - null); console.log(undefined * null); console.log(undefined / null); console.log(undefined % null); console.log(undefined ** null);
console.log(undefined + '');
|
null
与任何值进行算术运算时, null
会被转换为数字 0。
1 2 3 4 5 6 7 8 9 10 11 12 13
| console.log(null + 3); console.log(null - 3); console.log(null * 3); console.log(null / 3); console.log(null % 3); console.log(null ** 3);
console.log(null + null); console.log(null - null); console.log(null * null); console.log(null / null); console.log(null % null); console.log(null ** null);
|
其他类型的数据参与数学运算
加法
如果有一个操作数是NaN,那么结果为NaN。除了字符串会变成字符串(只有加法会这样——拼接)外,其他都会先进行隐式类型传唤再进行计算。
1 2 3 4 5 6 7 8 9 10 11
| console.log('10' + 1); console.log('' + 1); console.log(1 + 2 + '3'); console.log('' + true) console.log('' + NaN) console.log('' + undefined) console.log('' + null) console.log('' + Infinity) console.log('' + -Infinity) console.log('' + [1,2,3]) console.log('' + {a:1,b:2})
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| console.log(1 + NaN); console.log(1 + true); console.log(1 + false); console.log(1 + null); console.log(1 + undefined); console.log(1 + []); console.log([] + 1); console.log([] + []); console.log(1 + [1,2,3]); console.log(1 + {}); console.log({} + 1); console.log({} + {}); console.log(1 + {name:'li'}); console.log([] + {}); console.log({} + []); console.log([1,2,3] + {name:'li'}); console.log(new Date() + 1);
|
减法
先将其他类型隐式转成number
类型再进行计算,如果转不了则变成NaN
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| console.log(1 - NaN); console.log(1 - true); console.log(1 - false); console.log(1 - null); console.log(1 - undefined); console.log(1 - []); console.log([] - 1); console.log([] - []); console.log(1 - [12]); console.log(1 - [null]); console.log(1 - [undefined]); console.log(1 - [NaN]); console.log(1 - [Infinity]); console.log(1 - [-Infinity]); console.log(1 - [[]]); console.log(1 - [[1]]); console.log(1 - [{}]); console.log(1 - [1,2,3]); console.log(1 - {}); console.log({} - 1); console.log({} - {}); console.log(1 - {name:'li'}); console.log([] - {}); console.log({} - []); console.log([1,2,3] - {name:'li'}); console.log(new Date() - 1);
|
乘法
和减法一样:先将其他类型隐式转成number
类型再进行计算,如果转不了则变成NaN
。
除法
也和减法一样:先将其他类型隐式转成number
类型再进行计算,如果转不了则变成NaN
。
但要注意:除以0(或隐式转化成0)为Infinity
,除以Infinity
为0,除以-Infinity
为-0
取模
- 如果左右两侧均是数值,则进行除法计算,结果返回余数
- 任何一侧为NaN,则结果返回NaN
- 只要除数是0(或隐式转化成0) ,则结果返回NaN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| console.log(1 % NaN); console.log(1 % true); console.log(1 % false); console.log(1 % null); console.log(1 % undefined); console.log(1 % []); console.log([] % 1); console.log([] % []); console.log(1 % [12]); console.log(1 % [null]); console.log(1 % [undefined]); console.log(1 % [NaN]); console.log(1 % [Infinity]); console.log(1 % [-Infinity]); console.log(1 % [[]]); console.log(1 % [[1]]); console.log(1 % [{}]); console.log(1 % [1,2,3]); console.log(1 % {}); console.log({} % 1); console.log({} % {}); console.log(1 % {name:'li'}); console.log([] % {}); console.log({} % []); console.log([1,2,3] % {name:'li'}); console.log(new Date() % 1);
|
加号+与减号-
- 操作数是Number类型,无影响(不论是正号还是负号,对NaN都是无影响)
- 操作数是其他类型,它具有转化成Number类型的功能,
+a
效果与Number(a)
相同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| console.log(+'21') console.log(-'21') console.log(+[]); console.log(+[1]); console.log(+[1,2]); console.log(+{}); console.log(-undefined)
let str = '123'; console.log(str + 2); console.log(+str + 2);
let num1 = 10; let num2 = 20; console.log(num1 + num2); console.log(num1 + '' + num2);
|
自增与自减
- 前置型
++a
:先自增再使用
- 后置型
a++
:先使用再自增
- 如果有一侧不为Number类型,则(根据对应的规则)转为数字类型后,再进行计算。
比较运算符
字符 |
说明 |
> |
大于 |
< |
小于 |
>= |
大于等于 |
<= |
小于等于 |
规则:
- 如果左右两侧都是数值,则数值之间进行比较
- 如果左右两侧都是字符串,则根据字符串对应的字符编码值
- 如果有一侧是NaN,则结果得到false
- 如果是
null
,undefined
,true
,false
,则(会根据对应的规则)进行转换,然后进行比较
undefined
用 >
, <
, <=
, >=
与任何值比较时都为false
- 任何与 NaN 进行的比较运算(无论是使用
>
、 <
、 >=
、 <=
还是 ==
和 ===
)都会返回 false
。这是因为 NaN 不等于任何值,包括它自己。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| console.log(1 > 2) console.log(1 > NaN) console.log('hello' > 'hey' ) console.log(1 > 'hello') console.log(2 >'1') console.log(1 > null) console.log(null > null) console.log(null >= undefined) console.log(null <= undefined) console.log(null >= 0) console.log(null == 0) console.log(1 > false) console.log(NaN >= NaN) console.log('hello' < false)
|
相等操作符
字符 |
说明 |
== |
相等 |
!= |
不等 |
=== |
全等 |
!== |
全不等 |
==
和 !=
不会比较类型,如果类型不一致,会先进行隐式类型转换再进行比较
===
和 !==
是严格相等,会先比较类型是否相同,如果类型不同直接false
,类型相同再比较值是否相同
- NaN不等于任何类型的数值,包括自己本身,所以都返回
false
;
- 如果都是String类型的话,比较字符编码值,如果完全一致,则返回
true
,否则返回false
;
- 如果两侧都是Number类型数值,比较值是否相同;
- 如果两边都是Object类型,则比较地址是否一致;
null == undefined
返回true
- 如果一侧是
String
,一侧是Number
,将String
转换为NaN之后,进行比较(如果String是数值类型则将String转换为Number进行比较)
- 如果一侧是Boolean,则将布尔值转换为Number类型后,再根据上述规则进行比较;
1 2 3 4 5 6 7 8 9 10
| console.log(null == undefined) console.log(null == null) console.log(undefined == undefined) console.log(1 == '1') console.log(null == NaN) console.log(null === undefined) console.log(null === null) console.log(undefined === undefined) console.log(1 === '1') console.log(null === NaN)
|
注意:全等===
有个缺陷: NaN === NaN
的结果是false
,可以用Object.is()
:
Object.is(NaN, NaN)
结果是true
Object.is(0, -0)
结果是false
赋值运算符
=
:普通赋值运算符
+=
:加法赋值运算符
-=
:减法赋值运算符
*=
:除法赋值运算符
/=
:乘法赋值运算符
%=
:取模赋值运算符
**=
:指数赋值运算符
<<=
:左移赋值运算符
>>=
:右移赋值运算符
>>>=
:无符号右移赋值运算符,将左侧的变量向右移动右侧的值所指定的位数,且用 0 填充左侧的空位,并将结果赋给左侧的变量。
&&=
:与赋值运算符,如果左侧的操作数为 true
,则将右侧的值赋给左侧的变量;否则将 false
赋给左侧的变量。
||=
:或赋值运算符,如果左侧的操作数为 false
,则将右侧的值赋给左侧的变量;否则将 true
赋给左侧的变量。
??=
:空值合并赋值运算符,x ??= y
等同于 x ?? (x = y)
,只有运算符左侧的值为 null
或 undefined
时 才会继续右侧的运算