目录
0、!! 双重逻辑非操作符
1、?? 操作符 空值合并/空判断 ✅
2、?. 可选链运算符
3、??= 操作符 逻辑空值赋值运算符
4、三元运算符
5、~~ 操作符 双位运算符
6、&&与 ||或 短路运算符
7、| 0 取整
8、& 1 判断奇偶数
9、_ 数值分割符
10、void 运算符
11、Js操作符的优先级
一些常用的操作符可以让你的前端代码更加简洁明了。本文整理一些 JS 中常用的运算符/操作符,其目的在于简化代码。
双重逻辑非操作符 !!
的作用是将一个值转换为其对应的布尔值。在这个场景下,它用于判断用户输入的信息是否存在(即不为空)。如果用户输入非空内容,!!user
的结果为 true
,执行相应的逻辑;如果用户未输入任何内容,!!user
的结果为 false
,则不执行相应的逻辑。
空值合并运算符 , 如果第一个参数不是null或者undefined,这个运算符将返回第一个参数,否则,它将返回第二个参数
null ?? 3 //3
undefined ?? 3 //3
7 ?? 3 //7
在JS,如果读取对象里的某个属性时,往往需要先判断对象是否存在,以防止报错。
let a = (obj && obj.name) || 'default';
以上代码可以使用 null 传导符简写为
let a = obj ?. name || 'default';
详细说明,可以见官网说明:
不过需要注意的是:
这个赋值操作符只有在当前值为空或未定义的情况下才会赋一个新的值。
let a = null
const b = 5
console.log(a ??= b) // => 5
console.log(a = (a ?? b)) // => 5
val 为真,则 a 取值 ifTrue ,否则取值 ifFalse
const a = val ? ifTrue : ifFalse
可以使用双位操作符来替代正数的 Math.floor( ),替代负数的Math.ceil( )。双否定位操作符的优势在于它执行相同的操作运行速度更快。
Math.floor(4.9) === 4 //true
// 简写为:
~~4.9 === 4 //true
不过要注意,对正数来说 ~~ 运算结果与 Math.floor( ) 运算结果相同,而对于负数来说与Math.ceil( )的运算结果相同:
~~4.5 // 4
Math.floor(4.5) // 4
Math.ceil(4.5) // 5
~~-4.5 // -4
Math.floor(-4.5) // -5
Math.ceil(-4.5) // -4
&&为取假运算,从左到右依次判断,如果遇到一个假值,就返回假值,以后不再执行,否则返回最后一个真值
||为取真运算,从左到右依次判断,如果遇到一个真值,就返回真值,以后不再执行,否则返回最后一个假值
let param1 = expr1 && expr2
let param2 = expr1 || expr2
对一个数字| 0可以取整,负数也同样适用,num | 0
1.3 | 0 // 1
-1.9 | 0 // -1
对一个数字& 1可以判断奇偶数,负数也同样适用,num & 1
const num=3;
!!(num & 1) // true
!!(num % 2) // true
ES2021 引入了数值分割符 _ ,在数值组之间提供分隔,使一个长数值读起来更容易。Chrome 已经提供了对数值分割符的支持,可以在浏览器里试起来。
let number = 100_0000_0000_0000 // 0太多了不用数值分割符眼睛看花了
console.log(number) // 输出 100000000000000
此外,十进制的小数部分也可以使用数值分割符,二进制、十六进制也可以使用数值分割符
0x11_1 === 0x111 // true 十六进制
0.11_1 === 0.111 // true 十进制的小数
0b11_1 === 0b111 // true 二进制
void 运算符 对给定的表达式进行求值,然后返回 undefined
可以用来给在使用立即调用的函数表达式(IIFE)时,可以利用 void 运算符让 JS 引擎把一个 function 关键字识别成函数表达式而不是函数声明。
function iife() { console.log('foo') }() // 报错,因为JS引擎把IIFE识别为了函数声明
void function iife() { console.log('foo') }() // 正常调用
~function iife() { console.log('foo') }() // 也可以使用一个位操作符
(function iife() { console.log('foo') })() // 或者干脆用括号括起来表示为整体的表达式
还可以用在箭头函数中避免传值泄漏,箭头函数,允许在函数体不使用括号来直接返回值。这个特性给用户带来了很多便利,但有时候也带来了不必要的麻烦,如果右侧调用了一个原本没有返回值的函数,其返回值改变后,会导致非预期的副作用。
const func = () => void customMethod() // 特别是给一个事件或者回调函数传一个函数时
安全起见,当不希望函数返回值是除了空值以外其他值,应该使用 void 来确保返回 undefined,这样,当 customMethod 返回值发生改变时,也不会影响箭头函数的行为。
JavaScript 运算符优先级,是描述在计算机运算计算表达式时执行运算的先后顺序。先执行具有较高优先级的运算,然后执行较低优先级的运算。例如,我们常说的先执行相乘和除,再执行加减运算。
下面的表格将所有运算符按照优先级的不同从高(19)到低(1)排列。
请注意,下表中故意不包含展开语法(Spread syntax) —— 原因可以引用Stack Overflow 上的一个回答,“展开语法不是一个运算符,因此没有优先级。它是数组字面量和函数调用(和对象字面量)语法的一部分。”
优先级 | 运算符类型 | 结合性 | 运算符 |
---|---|---|---|
19 | 分组 | n/a(不相关) | ( … ) |
18 | 成员访问 | 从左到右 | … . … |
需计算的成员访问 | 从左到右 | … [ … ] |
|
new(带参数列表) | n/a | new … ( … ) |
|
函数调用 | 从左到右 | … ( … ) |
|
可选链(Optional chaining) | 从左到右 | ?. |
|
17 | new(无参数列表) | 从右到左 | new … |
16 | 后置递增 | n/a | … ++ |
后置递减 | … -- |
||
15 | 逻辑非 (!) | 从右到左 | ! … |
按位非 (~) | ~ … |
||
一元加法 (+) | + … |
||
一元减法 (-) | - … |
||
前置递增 | ++ … |
||
前置递减 | -- … |
||
typeof | typeof … |
||
void | void … |
||
delete | delete … |
||
await | await … |
||
14 | 幂 (**) | 从右到左 | … ** … |
13 | 乘法 (*) | 从左到右 | … * … |
除法 (/) | … / … |
||
取余 (%) | … % … |
||
12 | 加法 (+) | 从左到右 | … + … |
减法 (-) | … - … |
||
11 | 按位左移 (<<) | 从左到右 | … << … |
按位右移 (>>) | … >> … |
||
无符号右移 (>>>) | … >>> … |
||
10 | 小于 (<) | 从左到右 | … < … |
小于等于 (<=) | … <= … |
||
大于 (>) | … > … |
||
大于等于 (>=) | … >= … |
||
in | … in … |
||
instanceof | … instanceof … |
||
9 | 相等 (==) | 从左到右 | … == … |
不相等 (!=) | … != … |
||
一致/严格相等 (===) | … === … |
||
不一致/严格不相等 (!==) | … !== … |
||
8 | 按位与 (&) | 从左到右 | … & … |
7 | 按位异或 (^) | 从左到右 | … ^ … |
6 | 按位或 (|) | 从左到右 | … | … |
5 | 逻辑与 (&&) | 从左到右 | … && … |
4 | 逻辑或 (||) | 从左到右 | … || … |
空值合并 (??) | 从左到右 | … ?? … |
|
3 | 条件(三元)运算符 | 从右到左 | … ? … : … |
2 | 赋值 | 从右到左 | … = … |
… += … |
|||
… -= … |
|||
… **= … |
|||
… *= … |
|||
… /= … |
|||
… %= … |
|||
… <<= … |
|||
… >>= … |
|||
… >>>= … |
|||
… &= … |
|||
… ^= … |
|||
… |= … |
|||
… &&= … |
|||
… ||= … |
|||
… ??= … |
|||
1 | 逗号 / 序列 | 从左到右 | … , … |
圆括号用于改变由运算符优先级确定的计算顺序。这就是说,先计算完圆括号内的表达式,然后再将它的值用于表达式的其余部分。
其实在运算过程中,和其他语言一样,最好直接带上括号,如var a = 1; a = (a + 100) >>(a+1); 和 var a = 1; a = a + 100>>a+1;结果都是25,运算顺序也一样,前面的可读性更好吧?