这些 JS 中强大的操作符,总有几个你没听说过
JS 里的操作符大家每天都在使用,还有一些 ES2020、ES2021 新加的实用操作符,这些共同构成了 JS 灵活的语法生态。本文除介绍常用的操作符之外,还会介绍 JS 里一些不常用但是很强大的操作符,下面我们一起来看看吧~
1. 数值分割符 _
ES2021 引入了数值分割符 _
,在数值组之间提供分隔,使一个长数值读起来更容易。Chrome 已经提供了对数值分割符的支持,可以在浏览器里试起来。
此外,十进制的小数部分也可以使用数值分割符,二进制、十六进制里也可以使用数值分割符。
2. 逗号运算符 ,
什么,逗号也可以是运算符吗?是的,曾经看到这样一个简单的函数,将数组的第一项和第二项调换,并返回两项之和:
逗号操作符对它的每个操作数求值(从左到右),并返回最后一个操作数的值。
会返回最后一个表达式 expr3
的结果,其他的表达式只会进行求值。
3. 零合并操作符 ??
零合并操作符 ??
是一个逻辑操作符,当左侧的操作数为 null
或者 undefined
时,返回右侧操作数,否则返回左侧操作数。
空值合并操作符一般用来为常量提供默认值,保证常量不为 null
或者 undefined
,以前一般使用 ||
来做这件事 variable = variable || 'bar'
。然而,由于 ||
是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0
, ''
, NaN
, null
, undefined
)都不会被返回。这导致如果你使用 0
、''
、NaN
作为有效值,就会出现不可预料的后果。
正因为 ||
存在这样的问题,而 ??
的出现就是解决了这些问题,??
只会在左侧为 undefined
、null
时才返回后者,??
可以理解为是 ||
的完善解决方案。
可以在浏览器中执行下面的代码感受一下:
另外在赋值的时候,可以运用赋值运算符的简写 ??=
4. 可选链操作符 ?.
可选链操作符 ?.
允许读取位于连接对象链深处的属性的值,而不必验证链中的每个引用是否有效。?.
操作符的功能类似于 .
链式操作符,不同之处在于,在引用为 null
或者 undefined
的情况下不会引起错误,该表达式短路返回值是 undefined
。
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。
以前可能会通过 obj && obj.a && obj.a.b
来获取一个深度嵌套的子属性,现在可以直接 obj?.a?.b
即可。
可选链除了可以用在获取对象的属性,还可以用在数组的索引 arr?.[index]
,也可以用在函数的判断 func?.(args)
,当尝试调用一个可能不存在的方法时也可以使用可选链。
调用一个对象上可能不存在的方法时(版本原因或者当前用户的设备不支持该功能的场景下),使用可选链可以使得表达式在函数不存在时返回 undefined
而不是直接抛异常。
5. 私有方法/属性
在一个类里面可以给属性前面增加 #
私有标记的方式来标记为私有,除了属性可以被标记为私有外,getter/setter
也可以标记为私有,方法也可以标为私有。
6. 位运算符 >> 与 >>>
有符号右移操作符 >>
将第一个操作数向右移动指定的位数,多余的位移到右边被丢弃,高位补其符号位,正数补 0,负数则补 1。因为新的最左位与前一个最左位的值相同,所以符号位(最左位)不会改变。
正数的好理解,负数怎么理解呢,负数在计算机中存储是按照补码来存储的,补码的计算方式是取反加一,移位时将补码形式右移,最左边补符号位,移完之后再次取反加一求补码获得处理后的原码。
一般我们用 >>
来将一个数除 2,相当于先舍弃小数位然后进行一次 Math.floor
:
无符号右移操作符 >>>
,将符号位作为二进制数据的一部分向右移动,高位始终补 0,对于正整数和算数右移没有区别,对于负数来说由于符号位被补 0,成为正数后就不用再求补码了,所以结果总是非负的。即便右移 0 个比特,结果也是非负的。
可以这样去理解
左移运算符 <<
与之类似,左移很简单左边移除最高位,低位补 0:
PS:JS 里面没有无符号左移,而且其他语言比如 JAVA 也没有无符号左移。
7. 位运算符 & 与 |
位运算符是按位进行运算,&
与、|
或、~
非、^
按位异或:
使用位运算符时会抛弃小数位,我们可以利用这个特性来给数字取整,比如给任意数字 &
上二进制的 32 个 1,或者 |
上 0,显而易见后者简单些。
所以我们可以对一个数字 | 0
来取整,负数也同样适用
判断奇偶数除了常见的取余 % 2
之外,也可以使用 & 1
,来判断二进制数的最低位是不是 1,这样除了最低位之外都被置 0,取余的结果只剩最低位,是不是很巧妙。负数也同样适用:
8. 双位运算符 ~~
可以使用双位操作符来替代正数的 Math.floor( )
,替代负数的 Math.ceil( )
。双否定位操作符的优势在于它执行相同的操作运行速度更快。
不过要注意,对正数来说 ~~
运算结果与 Math.floor( )
运算结果相同,而对于负数来说与 Math.ceil( )
的运算结果相同:
PS:注意
~~(num/2)
方式和num >> 1
在值为负数时的差别
9. 短路运算符 && 与 ||
我们知道逻辑与 &&
与逻辑或 ||
是短路运算符,短路运算符就是从左到右的运算中前者满足要求,就不再执行后者了。
可以理解为:
&&
为取假运算,从左到右依次判断,如果遇到一个假值,就返回假值,以后不再执行,否则返回最后一个真值||
为取真运算,从左到右依次判断,如果遇到一个真值,就返回真值,以后不再执行,否则返回最后一个假值
因此可以用来做很多有意思的事,比如给变量赋初值:
如果 variable1
是真值就直接返回了,后面短路就不会被返回了,如果为假值,则会返回后面的foo
。
也可以用来进行简单的判断,取代冗长的if
语句:
如果 param
如果为真值则返回 param.prop
属性,否则返回 param
这个假值,这样在某些地方防止 param
为 undefined
的时候还取其属性造成报错。
10. void 运算符
void
运算符 对给定的表达式进行求值,然后返回 undefined
可以用来给在使用立即调用的函数表达式(IIFE)时,可以利用 void
运算符让 JS 引擎把一个 function
关键字识别成函数表达式而不是函数声明。
还可以用在箭头函数中避免传值泄漏,箭头函数,允许在函数体不使用括号来直接返回值。这个特性给用户带来了很多便利,但有时候也带来了不必要的麻烦,如果右侧调用了一个原本没有返回值的函数,其返回值改变后,会导致非预期的副作用。
安全起见,当不希望函数返回值是除了空值以外其他值,应该使用 void
来确保返回 undefined
,这样,当 customMethod 返回值发生改变时,也不会影响箭头函数的行为。
11. 其他常用操作符
三元表达式:很简单了,大家经常用,
expr ? expr1 : expr2
如果expr
为真值则返回expr1
,否则返回expr2
赋值运算符简写:加法赋值
+=
、减法赋值-=
、乘法赋值*=
、除法赋值/=
、求幂赋值**=
、按位或复制|=
、按位与赋值&=
、有符号按位右移赋值>>=
、无符号按位右移赋值>>>=
、逻辑空赋值??=
....求幂运算符:
var1 ** var2
相当于Math.pow
,结果为var1
的var2
次方
12. 操作符优先级
正因为有操作符优先级,所以 variable = 1, 2
的含义是将变量先赋值为 1,再返回数字 2,而不是变量赋值给 1, 2
的返回值 2,这是因为 =
运算符的优先级高于 ,
逗号运算符。再比如表达式 6 - 2 * 3 === 0 && 1
,- * === &&
这四个运算符优先级最高的 *
先运算,然后 -
运算符结果为 0,===
运算符优先级高于 &&
而 true && 1
的结果为 1,所以这就是运算的结果。
下面的表将运算符按照优先级的不同从高(20)到低(1)排列,但这个不是最新的,至少没包括可选链,建议参考这个表或者 MDN。
网上的帖子大多深浅不一,甚至有些前后矛盾,在下的文章都是学习过程中的总结,如果发现错误,欢迎留言指出,如果本文帮助到了你,别忘了点赞支持一下哦,你的点赞是我更新的最大动力!(收藏不点赞,都是耍流氓 🤣)~
参考文档:
PS:本文收录在在下的博客 Github - SHERlocked93/blog 系列文章中,欢迎大家关注我的公众号 前端下午茶
,直接搜索即可添加或者点这里添加,持续为大家推送前端以及前端周边相关优质技术文,共同进步,一起加油~
版权声明: 本文为 InfoQ 作者【前端下午茶】的原创文章。
原文链接:【http://xie.infoq.cn/article/60a5a6cb09f36b48b8f5cffdd】。文章转载请联系作者。
评论