🧮 JavaScript 运算符
运算符也称为操作符,对一个或多个值进行运算或者操作。
# 算术运算符
运算符 | 描述 | 例子 | x 结果 | y 结果 |
---|---|---|---|---|
+ | 加法 | x=y+2 | 7 | 5 |
- | 减法 | x=y-2 | 3 | 5 |
* | 乘法 | x=y*2 | 10 | 5 |
/ | 除法 | x=y/2 | 2.5 | 5 |
% | 取模 | x=y%2 | 1 | 5 |
** | 求幂 | x=y**2 | 25 | 5 |
++ | 自增 | x=++y | 6 | 6 |
x=y++ | 5 | 6 | ||
-- | 自减 | x=--y | 4 | 4 |
x=y-- | 5 | 4 |
特殊的二元运算:除了加法以外,对非
Number
类型的值进行运算时,都会先转换为Number
然后在做运算。x = 6 - '2' // 4 y = '6' / '2' // 3
1
2对于加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。任何值和字符串做加法,都会先转换为字符串,然后再拼串。二元
+
是唯一一个以这种方式支持字符串的运算符。x = 5 + 5; y = "5" + 5; // '55' z = "hello" + 5; // 'hello5' // 特别地, a = 2 + 2 + '1' // '41'
1
2
3
4
5
6注意:自增 / 自减只能应用于变量。试一下,将其应用于数值(比如
5++
)则会报错。运算符
++
和--
可以置于变量前,也可以置于变量后。- 当运算符置于变量后,被称为「后置形式」:
counter++
。 - 当运算符置于变量前,被称为「前置形式」:
++counter
。
所有的运算符都有返回值。自增 / 自减也不例外。前置形式返回一个新的值,但后置返回原来的值(做加法 / 减法之前的值)。
- 前置形式:对
counter
做自增运算,返回的是新的值2
。因此alert
显示的是2
。
let counter = 1; let a = ++counter; // (*) alert(a); // 2
1
2
3
4- 后置形式:它同样对
counter
做加法,但是返回的是 旧值(做加法之前的值)。因此alert
显示的是1
。
let counter = 1; let a = counter++; alert(a); // 1
1
2
3
4- 但是如果自增 / 自减的值不会被使用,那么两者形式没有区别:
let counter = 0; counter++; ++counter; alert( counter );
1
2
3
4- 对变量进行自增操作,并且 需要立刻使用自增后的值,那么我们需要使用前置形式:
alert(++counter); // 1
;想要将一个数加一,但是想使用其自增之前的值,那么需要使用后置形式:alert( counter++ ); // 0
。
自增 / 自减和其它运算符的对比:
++/--
运算符同样可以在表达式内部使用。它们的优先级比绝大部分的算数运算符要高。let counter = 1; alert( 2 * ++counter ); // 4
1
2let counter = 1; alert( 2 * counter++ ); // 2
1
2上述列子降低了代码的可读性,并不推荐。还是建议依照「一行一个行为」的原则。
let counter = 1; alert( 2 * counter ); counter++;
1
2
3- 当运算符置于变量后,被称为「后置形式」:
# 一元运算符
表示运算时操作数只要一个:
+
正号,不会对数字值产生任何影响,但是可以 ** 将一个非数字转换为数字:** 它的效果和Number(...)
相同,但是更加简短。let a = true; a = +a; // 1 let b = "" b = +"" // 0
1
2
3
4
5经常会有将字符串转化为数字的需求。比如,如果我们正在从 HTML 表单中取值,通常得到的都是字符串。如果我们想对它们求和:
let apples = "2"; let oranges = "3"; // 在二元运算符加号起作用之前,所有的值都被转化为了数字 alert( +apples + +oranges ); // 5 // 更长的写法 // alert( Number(apples) + Number(oranges) ); // 5
1
2
3
4
5
6
7也可以从上面例子看出,一元运算符先于二元运算符作用于运算元。
-
符号,对一个数字进行符号位取反:var a = true; a = -a; // -0
1
2对字符串运用会得到结果
NaN
;
# 运算符优先级
在 JavaScript 中有众多运算符。每个运算符都有对应的优先级数字。** 数字越大,越先执行。** 如果优先级相同,则按照由左至右的顺序执行。
# 逻辑运算符
逻辑运算符 (javascript.info) (opens new window)
逻辑运算符用于测定变量或值之间的逻辑。
运算符 | 描述 | 例子 |
---|---|---|
&& | and 所有为真才为真 | (x < 10 && y> 1) 为 true |
|| | or 有一个为真即为真 | (x==5 || y==5) 为 false |
! | not | !(x==y) 为 true |
或
||
运算符的应用:大多数情况下,逻辑或||
会被用在if
语句中,用来测试是否有 任何 给定的条件为true
。let hour = 9; if (hour < 10 || hour > 18) { alert( 'The office is closed.' ); }
1
2
3
4
5或运算寻找第一个真值:一个或运算
||
的链,将返回第一个真值,如果不存在真值,就返回该链的最后一个值。获取变量列表或者表达式中的第一个真值。:
let firstName = ""; let lastName = ""; let nickName = "SuperCoder"; alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder
1
2
3
4
5短路求值:
||
对其参数进行处理,直到达到第一个真值,然后立即返回该值,而无需处理其他参数。如果操作数不仅仅是一个值,而是一个有副作用的表达式,例如变量赋值或函数调用,那么这一特性的重要性就变得显而易见了。true || alert("not printed"); // alert没有被运行 false || alert("printed");
1
2
与运算寻找第一个假值:与和或运算很像。区别就是与运算返回第一个假值,而或运算返回第一个真值。
// 如果第一个操作数是真值, // 与运算返回第二个操作数: alert( 1 && 0 ); // 0 alert( 1 && 5 ); // 5 // 如果第一个操作数是假值, // 与运算将直接返回它。第二个操作数会被忽略 alert( null && 5 ); // null alert( 0 && "no matter what" ); // 0
1
2
3
4
5
6
7
8
9如果所有的值都是真值,最后一个值将会被返回:
alert( 1 && 2 && 3 ); // 3,最后一个值
1
与运算
&&
在或运算||
之前进行:与运算&&
的优先级比或运算||
要高。所以代码a && b || c && d
跟&&
表达式加了括号完全一样:(a && b) || (c && d)
。使用非运算
!!
有时候用来将某个值转化为布尔类型:alert( !!"non-empty string" ); // true alert( !!null ); // false
1
2
# ??
空值合并
a ?? b
的结果是:
- 如果
a
是已定义的,则结果为a
,- 如果
a
不是已定义的,则结果为b
。
如果第一个参数不是 null/undefined
,则 ??
返回第一个参数。否则,返回第二个参数。
应用场景:
提供默认值:如果
user
的值不为null/undefined
则显示user
,否则显示匿名
:let user; alert(user ?? "匿名");
1
2let user = "John"; alert(user ?? "匿名");
1
2选择出第一个非
null/undefined
的值。let firstName = null; let lastName = null; let nickName = "Supercoder"; // 显示第一个已定义的值: alert(firstName ?? lastName ?? nickName ?? "匿名"); // Supercoder
1
2
3
4
5
6
??
与||
比较:
- 或运算符
||
可以以与??
运算符相同的方式使用。(alert(firstName || lastName || nickName || "Anonymous");
同理)- 但是,或
||
运算符先于??
出现,它自 JavaScript 诞生就存在。空值合并运算符??
是最近才被添加到 JavaScript 中的。||
返回第一个 真 值。??
返回第一个 已定义的 值。
||
无法区分false
、0
、空字符串""
和null/undefined
。它们都一样 —— 假值(falsy values)。如果其中任何一个是||
的第一个参数,那么我们将得到第二个参数作为结果。- 优先级:
??
运算符的优先级与||
相同。空值合并运算符在=
和?
运算前计算,但在大多数其他运算(例如+
和*
)之后计算。- 不能将
??
与||
或&&
一起使用,JavaSript 会触发语法错误。除非使用括号明确指定了优先级。
# 赋值运算符
若 x=10 和 y=5:
运算符 | 例子 | 等同于 | 运算结果 |
---|---|---|---|
= | x=y | x=5 | |
+= | x+=y | x=x+y | x=15 |
-= | x-=y | x=x-y | x=5 |
*= | x*=y | x=x*y | x=50 |
/= | x/=y | x=x/y | x=2 |
%= | x%=y | x=x%y | x=0 |
链式赋值:
let a, b, c; a = b = c = 2 + 2; // a = 4, b = 4, c = 4
1
2
3
4最好写为可读性更强的:
c = 2 + 2; b = c; a = c;
1
2
3
# 关系运算符
值的比较 (javascript.info) (opens new window)
比较值之间的关系:
- 如果关系成立则返回
true
,关系不成立则返回false
。 - 如果比较的两个值是非数值,会将其转换为
Number
然后再比较。 - 如果比较的两个值都是字符串,此时会比较字符串的 Unicode 编码,而不会转换为
Number
。
运算符 | 描述 | 比较 | 返回值 |
---|---|---|---|
== | 等于 | x==8 | false |
x==5 | true | ||
=== | 绝对等于(值和类型均相等) | x==="5" | false |
x===5 | true | ||
!= | 不等于 | x!=8 | true |
!== | 不绝对等于(值和类型有一个不相等,或两个都不相等) | x!=="5" | true |
x!==5 | false | ||
> | 大于 | x>8 | false |
< | 小于 | x<8 | true |
>= | 大于或等于 | x>=8 | false |
<= | 小于或等于 | x<=8 | true |
特殊的值:
NaN
和Undefined
:由于undefined
衍生自null
,所以null == undefined
会返回true
。 但是null === undefined
会返回false
;NaN
和任何数值都不相等,自身NaN == NaN
为false
;- 判断一个值是否
NaN
,使用isNaN()
函数;
# 三元运算符
先对条件表达式求值判断,如果判断结果为 true
,则执行语句 1,并返回执行结果;如果判断结果为 false
,则执行语句 2,并返回执行结果;
条件表达式 ? 语句1 : 语句2;
# 逗号运算符
逗号运算符 ,
是最少见最不常使用的运算符之一。逗号运算符能让我们处理多个语句,使用 ,
将它们分开。** 每个语句都运行了,但是只有最后的语句的结果会被返回。** 例如:
let a = (1 + 2, 3 + 4); // 只有 3 + 4 运行, 1 + 2 的结果被丢弃
alert( a );
2
3
逗号运算符的优先级:逗号运算符的优先级非常低,比
=
还要低,因此上面你的例子中圆括号非常重要。如果没有圆括号:a = 1 + 2, 3 + 4
会先执行+
,将数值相加得到a = 3, 7
,然后赋值运算符=
执行a = 3
,然后逗号之后的数值7
不会再执行,它被忽略掉了。相当于(a = 1 + 2), 3 + 4