按位操作符
按位操作符 - JavaScript | MDN
将其操作数当作32位的比特序列(二进制表示)
运算符 |
用法 |
描述 |
按位与(AND) |
a & b |
对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0 |
按位或(OR) |
a | b |
对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0 |
按位异或(XOR) |
a ^ b |
对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0 |
按位非(NOT) |
~ a |
反转操作数的比特位,即0变成1,1变成0 |
左移 |
a << b |
将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充 |
有符号右移 |
a >> b |
将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位 |
无符号右移 |
a >>> b |
将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充 |
有符号32位整数
所有的按位操作符的操作数都会被转成补码形式的有符号32位整数。
补码形式是指一个数的负对应值(如 5和-5)为数值的所有比特位反转后,再加1。
反转比特位即该数值进行’非‘位运算,也即该数值的反码。
314
00000000000000000000000100111010
~314
11111111111111111111111011000101
-314
11111111111111111111111011000110
补码保证了当一个数是正数时,其最左的比特位是0,当一个数是负数时,其最左的比特位是1。
因此,最左边的比特位被称为符号位。
0
00000000000000000000000000000000
-1
11111111111111111111111111111111
-2147483648 (-0x80000000)
10000000000000000000000000000000
2147483647 (0x7fffffff)
01111111111111111111111111111111
数字-2147483648 和 2147483647 是32位有符号数字所能表示的最小和最大整数。
& (按位与)
a |
b |
a & b |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
x & 0 = 0
x & -1 = x
9 & 14 = 8
| (按位或)
a |
b |
a | b |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
x | 0 = x
x | -1 = -1
9 | 14 = 15
1 | 0
1.6 | 0
0 | 0
-1 | 0
-1.9 | 0
[] | 0
{} | 0
'123456' | 0
'abcdef' | 0
1.23e2 | 0
-1.23e3 | 0
^ (按位异或)
a |
b |
a ^ b |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
x ^ 0 = x
x ^ -1 = ~x
x ^ x = 0
9 ^ 14 = 7
~ (按位非)
~x = -(x + 1)
9
~9 = -10
10
-10
~str.indexOf(searchFor)
<< (左移)
x << y = x * (2 ** y)
9 << 2
9 << 3
>> (有符号右移)
9 >> 2
-9 >> 2
-9 >> 0
>>> (无符号右移)
9 >>> 2
-9 >>> 2
-9 >>> 0
应用
标志位和掩码
let flags = 5
const FLAG_A = 1
const FLAG_B = 2
const FLAG_C = 4
const FLAG_D = 8
let mask = FLAG_A | FLAG_B | FLAG_D
if (flags & FLAG_C) {}
if ((flags & FLAG_B) || (flags & FLAG_C)) {}
mask = FLAG_B | FLAG_C
if (flags & mask) {}
mask = FLAG_C | FLAG_D
flags |= mask
mask = ~(FLAG_A | FLAG_C)
flags &= mask
mask = ~FLAG_A & ~FLAG_C
mask = FLAG_B | FLAG_C
flags = 12
flags ^= mask
flags ^= mask
flags = ~flags
转换片段
parseInt('1011', 2)
(11).toString(2)
自动化掩码创建
function createMask(...args) {
const len = args.length < 32 ? args.length : 32
let mask = 0
for (let i = 0; i < len; i++) {
mask |= args[i] << i
}
return mask
}
createMask(true, true, false, true)
createMask(false, false, true)
createMask(true)
createMask()
逆算法:从掩码得到布尔数组
function arrayFromMask(mask) {
if (mask > 0x7fffffff || mask < -0x80000000) {
throw new TypeError('arrayFromMask - out of range')
}
const arr = []
let shifted = mask
while (shifted) {
arr.push(Boolean(shifted & 1))
shifted >>>= 1
}
return arr
}
arrayFromMask(11)
arrayFromMask(4)
arrayFromMask(1)
arrayFromMask()
function createBinaryString(mask = 0) {
if (mask > 2147483647 || mask < -2147483648) {
throw new TypeError('arrayFromMask - out of range')
}
let sMask = ''
let shifted = mask
for (let i = 0; i < 32; i++) {
sMask += String(shifted >>> 31)
shifted <<= 1
}
return sMask;
}
createBinaryString(11)
createBinaryString(4)
createBinaryString(1)
createBinaryString()
判断奇偶性
- 奇数 & 1 = 1
- 偶数 & 1 = 0
- 奇数 % 2 = 1
- 偶数 % 2 = 0
取整 ~~ >> << >>> |
~~3.14
3.14 | 0
3.14 << 0
3.14 >> 0
3.14 >>> 0
~~3.9
3.9 | 0
3.9 << 0
3.9 >> 0
3.9 >>> 0
~~-3.14
-3.14 | 0
-3.14 << 0
-3.14 >> 0
-3.14 >>> 0
~~-3.9
-3.9 | 0
-3.9 << 0
-3.9 >> 0
-3.9 >>> 0
~~'abc'
'abc' | 0
'abc' << 0
'abc' >> 0
'abc' >>> 0
~~[]
[] | 0
[] << 0
[] >> 0
[] >>> 0
~~{}
({}) | 0
({}) << 0
({}) >> 0
({}) >>> 0
计算
Math.pow(2, 3)
2 ** 3
2 << 2
3 * Math.pow(2, 3)
3 << 3
9 / 2
9 >> 1
9 / 4
9 >> 2
比较两个数是否相等
1100 ^ 1100
1100 ^ 非1100
值交换
let a = 1
let b = 2
a ^= b
b ^= a
a ^= b
判断值的正负
function isPos(n) {
return n === (n >>> 0)
}
色值转换
function rgbToHex(rgb) {
const arr = rgb.split(/[^\d]+/)
const clr = arr[1] << 16 | arr[2] << 8 | arr[3]
return '#' + clr.toString(16)
}
rgbToHex('rgb(255, 68, 0)')
rgbToHex('rgb(255, 255, 0)')
function hexToRGB(hex) {
hex = hex.replace('#', '0x')
const r = hex >> 16
const g = hex >> 8 & 0xff
const b = hex & 0xff
return `rgb(${r}, ${g}, ${b})`
}
hexToRGB('#ff4400')
hexToRGB('#ffff00')
权限系统
|
赋予权限
&
校验权限
&~
删除权限
^
切换权限
const r = 0b100
const w = 0b010
const x = 0b001
let user = r | w
console.log(user.toString(2))
console.log((user & r) === r)
console.log((user & w) === w)
console.log((user & x) === x)
user = user & (~r)
console.log(user.toString(2))
console.log((user & r) === r)
user = user ^ r
console.log(user.toString(2))
console.log((user & r) === r)
user = user ^ r
console.log(user.toString(2))
console.log((user & r) === r)