按位操作符
(Bitwise operators) 将其操作数(operands)当作32位的比特序列(由0和1组成),而不是十进制、十六进制或八进制数值。例如,十进制数9,用二进制表示则为1001。按位操作符操作数字的二进制形式,但是返回值依然是标准的JavaScript数值(来自MDN)。
也就是将操作数转成一串32位的二进制。按位操作符进行运算前先要转成32位的二进制(超过32位的会被丢弃)。如何丢弃的?
丢弃前: 11100110111110100000000000000110000000000001
丢弃后: 10100000000000000110000000000001
二进制又是什么?二进制是一串比特序列(由0和1组成)
二进制怎么转?
我们的操作数一般都是十进制的,也就是十进制转二进制。
二进制转十进制:
00000000 00000000 00000000 00000101
=>
结果:1*2^0 + 0*2^1 + 1*2^1 = 5 (^表示次方)
十进制转二进制:
233
=>
对233及其结果依次除以2,将余数结果从右至左排序。
233 / 2 => 1
116 / 2 => 0
58 / 2 => 0
29 / 2 => 1
14 / 2 => 0
7 / 2 => 1
3 / 2 => 1
1 / 2 => 1
结果:00000000 00000000 00000000 11101001
**按位操作符种类**
运算符 | 用法 | 描述 |
---|---|---|
按位与 | a & b | 对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。 |
按位或 | a I b | 对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。 |
按位异或 | a ^ b | 对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。 |
按位非 | ~ a | 反转操作数的比特位,即0变成1,1变成0。 |
左移 | a << b | 将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。 |
有符号右移 | a >> b | 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。 |
无符号右移 | a >>> b | 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。 |
按位操作符可以这个理解,就是按照比特位进行相应的操作
& (按位与)
对每对比特位执行与操作。只有这对比特位都是 1 时,与操作后才是 1,否则为0。
9 = 00000000000000000000000000001001
14 = 00000000000000000000000000001110
14 & 9 = 00000000000000000000000000001000 = 8
| (按位或)
对每一对比特位执行或操作。如果这对比特位至少有一个为1 时,或操作后才是 1,否则为0。
9 = 00000000000000000000000000001001
14 = 00000000000000000000000000001110
14 | 9 = 00000000000000000000000000001111 = 15
^ (按位异或)
对每一对比特位执行异或操作。如果这对比特位不同时,异或操作后才是 1,否则为0。
9 = 00000000000000000000000000001001
14 ^ 9 = 00000000000000000000000000000111 = 7
~(按位非)
对每个特位执行非操作。 就是对比特位反转(即反码)。
9 = 00000000000000000000000000001001
~ 9 = 11111111111111111111111111110110 = -10
等等为什么是 -10?
由于第一位(符号位,即最左边的那位)是1,所以这个数是一个负数,为0则为整数。
JavaScript 内部采用补码形式表示负数,
即需要将这个数减去1,再取一次反,然后加上负号,才能得到这个负数对应的10进制值。
减1之后:11111111111111111111111111110101
再取反:00000000000000000000000000001010 = 10 然后加上负号,就是-10了
<<(左移)
该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充。
9 = 00000000000000000000000000001001
14 << 2 = 00000000000000000000000000100100 = 36
>>(有符号右移)
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。由于新的最左侧的位总是和以前相同,符号位没有被改变。所以被称作“符号传播”。
9 = 00000000000000000000000000001001
14 >> 2 = 00000000000000000000000000000010 = 2
>>> (无符号右移)
该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(译注:即便右移 0 个比特,结果也是非负的。)
9 = 00000000000000000000000000001001
14 >>> 2 = 00000000000000000000000000000010 = 2
按位操作符的用处
例子来源掘金大佬:https://juejin.im/post/5a98ea2f6fb9a028bb186f34#comment
function hexToRGB(hex) {
var hexx = hex.replace('#', '0x')
var r = hexx >> 16
var g = hexx >> 8 & 0xff
var b = hexx & 0xff
return `rgb(${r}, ${g}, ${b})`
}
function RGBToHex(rgb) {
var rgbArr = rgb.split(/[^\d]+/)
var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3]
return '#'+ color.toString(16)
}
hexToRGB('#ffffff') // 'rgb(255,255,255)'
RGBToHex('rgb(255,255,255)') // '#ffffff'