这是我参与更文挑战的第 26 天,活动详情查看:更文挑战
JavaScript
语言存在以下位运算:
运算符 | Usage | Description |
---|---|---|
按位与(& ) |
a & b |
在a,b的位表示中,每一个对应的位都为1则返回1, 否则返回0. |
按位或(| ) |
a | b |
在a,b的位表示中,每一个对应的位,只要有一个为1则返回1, 否则返回0. |
按位异或(^ ) |
a ^ b |
在a,b的位表示中,每一个对应的位,两个不相同则返回1,相同则返回0. |
按位非(~ ) |
~ a |
反转被操作数的位。 |
左移(<< ) |
a << b |
将a的二进制串向左移动b位,右边移入0. |
右移(>> ) |
a >> b |
把a的二进制表示向右移动b位,丢弃被移出的所有位.(注:算术右移左边空出的位是根据最高位是0和1来进行填充的) |
无符号右移,左边空出位用0填充(>>> ) |
a >>> b |
把a的二进制表示向右移动b位,丢弃被移出的所有位,并把左边空出的位都填充为0 |
还有以下逻辑运算:
运算符 | 范例 | 描述 |
---|---|---|
逻辑与 (&& ) |
expr1 && expr2 |
如果expr1 能被转换为false ,那么返回expr1 ;否则,返回expr2 。 |
逻辑或 (|| ) |
expr1 || expr2 |
如果expr1 能被转换为true ,那么返回expr1 ;否则,返回expr2 。 |
逻辑非 (! ) |
!expr |
1、将 expr 转化为布尔类型:true/false ,2、返回相反的布尔值 |
逻辑运算我们平时用的会比较多,主要用于条件判断,而位运算符就用得比较少。由于JavaScript
动态类型的特性,导致在很多情况下逻辑运算跟位运算会起到一些特殊的妙用。
逻辑运算
JavaScript
的逻辑运算不仅可以用于布尔值,也可以用于其它类型,返回值也可以是任意类型。
从上表的逻辑运算描述中可以发现,逻辑与和逻辑或运算,返回的并不是布尔值,而是操作数(可能是表达式)本身,而逻辑非运算则是返回一个布尔值。
我们利用逻辑运算符的相关特性,挖掘一些传统方式以外的用法。
1、短路求值
逻辑与和逻辑或运算都有一个「短路求值」特性,从左到右对参数进行处理,找到一个满足条件的参数就直接返回,如果前面的几个参数都不满足,就直接返回最后一个参数。
利用这个特性,可以做一些特别的操作如下:
// 返回第一个真值或假值
let result = null || 0 || 1 || undefined; // 1
let result = 1 && 2 && null && 3; // null
// 也可以是表达式,但建议还是用`if`,提高代码可读性
num > 0 && console.log('num 大于 0');
num > 0 || console.log('num 小于 0');
// 等价于
if (num > 0) {
console.log('num 大于 0');
}
if (num < 0) {
console.log('num 小于 0');
}
复制代码
2、布尔值转换
非运算常常被用于将操作数转换为布尔值,效果等同于Boolean
函数,如下所示。
!!"non-empty string" // true
!!null // false
复制代码
注意运算优先级,
!
>&&
>||
位运算
相比逻辑运算符,位运算符有更多的妙用。
1、位运算取整
在 JavaScript
内部,数值都是以64
位浮点数的形式储存,但是做位运算的时候,是以32
位带符号的整数进行运算的,并且返回值也是一个32
位带符号的整数。
借助这个特性,我们可以很方便的进行取整的操作:
~~ -3.14 // 3
3.14 >> 0) // 3
3.14 << 0) // 3
3.14 | 0 // 3
3.14 >>> 0 // 3, 不能对负数进行该操作
3.14 ^ 0 // 3
复制代码
需要注意的是,这种取整方法不适用超过32
位整数最大值2147483647
的数。
使用二进制否运算取整,是所有取整方法中最快的一种。
对字符串进行二进制运算,JavaScript
引擎会先调用Number
函数,将字符串转为数值。Number
的转换规则可见看LvLin
写的这篇JavaScript
类型转换。
2、2 次方的乘除实现
利用左移(右移)运算,可以迅速实现乘(除)以一个2
的指定次方,如下所示:
4 << 1 // 8
-4 << 1 // -8
4 >> 1 // 2
-4 >> 1 // -2
复制代码
3、两数互换
借助异或运算的特性,实现两数互换。
var a = 10;
var b = 99;
a ^= b, b ^= a, a ^= b;
复制代码
这是互换两个变量的值的最快方法。
4、颜色的 RGB 值与 HEX 值转换
综合使用多种位运算实现颜色的 RGB 值与 HEX 值转换。
// HEX 值转 RGB 值
function hexToRGB(hex) {
hex = hex.replace('#', '0x');
let r = hex >> 16;
let g = hex >> 8 & 0xff;
let b = hex & 0xff;
return `rgb(${r}, ${g}, ${b})`;
}
// RGB 值转 HEX 值
function RGBToHex(rgb) {
let rgbArr = rgb.split(/[^\d]+/)
let color = (rgbArr[1] << 16) | (rgbArr[2] << 8) | rgbArr[3]
return '#'+ color.toString(16)
}
复制代码
5、奇数偶数判断
通过按位与运算判断一个数的奇偶性,判断二进制最低一位是 0 还是 1。
2 & 1 // 0 , 偶数
5 & 1 // 1 , 奇数
复制代码
其它一些 JS 技巧(持续补充)
undefined == null // 空值的排除
NaN !== NaN // NaN 的判断
复制代码
6、除法异常处理
利用或运算,对除法运算的结果做取整以及异常处理。
let a = (num / 100) | 0;
(101 / 100) | 0 // 1
('abc' / 100) | 0 // 0
(Infinity / 1) | 0 // 0
复制代码