Dreamer Dreamer
首页
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)

lycpan233

白日梦想家
首页
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)
  • Vue

  • JavaScript

    • JavaScript部分特殊值判断记录
    • JavaScript各遍历方法对比
    • 防抖函数 Debounce
    • JavaScript 手撕深拷贝
    • JavaScript位运算应用场景
      • 位运算
      • 按位与(&)
        • 判断奇偶
        • 判断系统权限
        • lowbit
        • 计算二进制 1 的个数
      • 按位或(|)
        • 取整
        • 多选框
      • 按位异或(^)
        • 数值交换
      • 按位非(~)
        • 取整
      • 左移()
        • 扩大或缩小倍数并取整
      • 相关链接
    • 浅谈Cookie和Session的区别
    • js 快速创建二维数组并初始化
    • js 获取变量准确类型
  • 前端
  • JavaScript
lycpan233
2024-06-13
目录

JavaScript位运算应用场景

# 位运算

Operator Usage Description
按位与 AND a & b 在 a,b 的位表示中,每一个对应的位都为 1 则返回 1,否则返回 0.
按位或 OR a | b 在 a,b 的位表示中,每一个对应的位,只要有一个为 1 则返回 1,否则返回 0.
按位异或 XOR a ^ b 在 a,b 的位表示中,每一个对应的位,两个不相同则返回 1,相同则返回 0.
按位非 NOT ~ a 反转被操作数的位。
左移 shift a << b 将 a 的二进制串向左移动 b 位,右边移入 0.
算术右移 a >> b 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位。(译注:算术右移左边空出的位是根据最高位是 0 和 1 来进行填充的)
无符号右移 (左边空出位用 0 填充) a >>> b 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位,并把左边空出的位都填充为 0

# 按位与(&)

每一位都为 1, 则为 1, 否则为 0.

const a = 5; // 00000000000000000000000000000101
const b = 3; // 00000000000000000000000000000011

console.log(a & b); // 00000000000000000000000000000001
// Expected output: 1
1
2
3
4
5

快捷记忆方式,可以将其记为 && ,当两边都为 true 时,结果为 true,否则为 false。

# 判断奇偶

将奇数转为二进制数以后, 最后一位必然为1. 因此任意奇数与 1 进行位与(&),结果均为 1.

num & 1 === 1 // 判断奇偶
1

# 判断系统权限

我们以二进制的 0001(1)、0010(2)、0100(4)、1000(8) 这类 2^n 数字作为权限标识,再用位与运算判断是否存在权限。

例如: 用户拥有 0001(1) + 0010(2) 权限。 即 0011。 我们在代码中就可以做以下判断。

const userRight = 3; // 0011
/**
 * 是否拥有 1 权限。
 * 3 - 0011
 * 1 - 0001
 * & - 0001
 * 若结果 === 1 则为 true
 */
if (userRight === 1) { 
    doSomething...
}

/**
 * 是否拥有 8 权限。
 * 3 - 0011
 * 8 - 1000
 * & - 0000
 * 若结果 === 8 则为 true
 */
if (userRight === 8) { 
    doSomething...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# lowbit

获取某字符最低的那个1的位置。

function lowbit(x) {
  return x & -x;
}
1
2
3

原理解析:

lowbit( x ) = n & ( ~n + 1 ) = n & ( -n )

8 的二进制为 : 0 0 0 0 1 0 0 0

对 8 取反的二进制为 :1 1 1 1 0 1 1 1 (反码)

再对 取反8加一的二进制为 :1 1 1 1 1 0 0 0 (反码 + 1 = 补码)

进行与操作之后 : 0 0 0 0 1 0 0 0

就得到了我们的 lowbit ( 8 ) = 8

# 计算二进制 1 的个数

let count = 0;
while(x > =){
  x &= x - 1;
  count++;
}
1
2
3
4
5

# 按位或(|)

若其中任一位为 1,则为 1。

const a = 5; // 00000000000000000000000000000101
const b = 3; // 00000000000000000000000000000011

console.log(a | b); // 00000000000000000000000000000111
// Expected output: 7
1
2
3
4
5

# 取整

将小数于 0 进行位或运算,结果将会进行取整。

/**
 * 2.5 - 0010.1
 * 0   - 0000
 * |   - 0010
 */
const a = 2.5; // 0010.1
console.log(a | 0); // 0010
// Expected output: 2
1
2
3
4
5
6
7
8

# 多选框

多选的原理和位于运算思想有些类似,我们可以取0001(1)、0010(2)、0100(4)、1000(8)标识选项。

若选中 1 + 2,则进行位或运算

1 | 2 = 3. 
0001 | 0010 = 0011.
1
2

如果需要判断是否选中某个选项,则可以再采用位于运算, 判断是否选择 1 或 4.

3 & 1 = 1. // 选中
0011 & 0001 = 0001

3 & 4 = 0. // 未选中
0011 & 0100 = 0000
1
2
3
4
5

# 按位异或(^)

有且仅有一位是 1,才为 1。

const a = 5; // 00000000000000000000000000000101
const b = 3; // 00000000000000000000000000000011

console.log(a ^ b); // 00000000000000000000000000000110
// Expected output: 6
1
2
3
4
5

异或有几条性质,数学好点的可以尝试理解一下。

1、交换律
2、结合律 (a^b)^c == a^(b^c)
3、对于任何数x,都有 x^x=0,x^0=x
4、自反性: a^b^b=a^0=a;
1
2
3
4

# 数值交换

let a = 1;
let b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log(a, b); // 2, 1
1
2
3
4
5
6

原理同下,下面是四则运算版本

let a = 1;
let b = 2;
a = a + b;
b = a - b;
a = a - b;
1
2
3
4
5

# 按位非(~)

取反操作

const a = 5; // 00000000000000000000000000000101
const b = -3; // 11111111111111111111111111111101

console.log(~a); // 11111111111111111111111111111010
// Expected output: -6

console.log(~b); // 00000000000000000000000000000010
// Expected output: 2
1
2
3
4
5
6
7
8

# 取整

原理同位或操作

~~(-5.88) // -5
1

# 左移(<<)、右移(>>)

左移,右移都是移动位数。如: 0010 << 1 = 0100, 0010 >> 1 = 0001

const a = 5; // 00000000000000000000000000000101
const b = 2; // 00000000000000000000000000000010

console.log(b >> 3); // 00000000000000000000000000010100
// Expected output: 20
1
2
3
4
5
const a = 5; //  00000000000000000000000000000101
const b = 2; //  00000000000000000000000000000010
const c = -5; //  11111111111111111111111111111011

console.log(a >> b); //  00000000000000000000000000000001
// Expected output: 1

console.log(c >> b); //  11111111111111111111111111111110
// Expected output: -2
1
2
3
4
5
6
7
8
9

# 扩大或缩小倍数并取整

左移、右移 需要记住的是每移动一位,影响了多少倍率,这个倍率是 2^n。 举例:

10 >> 1 = (10 / 2^1); // 5

1
2

注意: 这里的取整是舍去小数位,不是 Math.floor()

# 相关链接

MDN 表达式与运算符 - 位运算符 (opens new window)

js中的位运算及应用场景 (opens new window)

深入讲解js中的位运算及实际用法 (opens new window)

位运算(&、|、^、~、>>、<<) (opens new window)

【位运算】深入理解并证明 lowbit 运算 (opens new window)

编辑 (opens new window)
上次更新: 2025/06/12, 08:45:25
JavaScript 手撕深拷贝
浅谈Cookie和Session的区别

← JavaScript 手撕深拷贝 浅谈Cookie和Session的区别→

最近更新
01
docker基础概念
02-26
02
js 获取变量准确类型
02-19
03
Mysql SQL 优化思路
02-18
更多文章>
Theme by Vdoing | Copyright © 2023-2025 Dreamer | MIT License
粤ICP备2025379918号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式