JavaScript 中的位操作符(Bitwise Operators)与典型应用场景
字数 1708 2025-12-11 03:41:00

JavaScript 中的位操作符(Bitwise Operators)与典型应用场景

在 JavaScript 中,位操作符用于直接操作数值的二进制位。虽然 JavaScript 的数字都是双精度浮点数,但进行位运算时,会先将操作数转换为 32 位有符号整数(补码表示),执行运算,然后再转换回 64 位浮点数。这个过程对开发者是透明的。

位操作符包括:

  • &(按位与 AND)
  • |(按位或 OR)
  • ^(按位异或 XOR)
  • ~(按位非 NOT)
  • <<(左移)
  • >>(有符号右移)
  • >>>(无符号右移)

理解这些操作符的关键在于明白它们对二进制位的操作逻辑。


1. 按位与(&)

原理:对两个操作数的每个对应位执行与操作,只有两个位都是 1 时,结果才为 1,否则为 0。

示例

let a = 5;    // 二进制:0101
let b = 3;    // 二进制:0011
let result = a & b; // 二进制:0001 → 十进制 1
console.log(result); // 输出:1

典型应用

  • 判断奇偶性(n & 1) === 0 表示 n 是偶数,(n & 1) === 1 表示 n 是奇数。
  • 权限控制:每个权限用一个二进制位表示,通过 & 检查是否具有某个权限。
  • 提取特定位:用掩码(mask)提取指定位。

2. 按位或(|)

原理:对两个操作数的每个对应位执行或操作,只要有一个位是 1,结果就为 1。

示例

let a = 5;    // 0101
let b = 3;    // 0011
let result = a | b; // 0111 → 十进制 7
console.log(result); // 输出:7

典型应用

  • 组合权限:将多个权限合并到一个值中。
  • 设置特定位为 1:使用掩码将指定位置 1。

3. 按位异或(^)

原理:对两个操作数的每个对应位执行异或操作,如果两个位不同,结果为 1;相同则为 0。

示例

let a = 5;    // 0101
let b = 3;    // 0011
let result = a ^ b; // 0110 → 十进制 6
console.log(result); // 输出:6

典型应用

  • 交换两个变量的值(不用临时变量)
    let x = 5, y = 3;
    x = x ^ y;
    y = x ^ y;
    x = x ^ y;
    console.log(x, y); // 输出:3, 5
    
  • 简单的加密/解密:用同一个密钥异或两次可还原数据。
  • 找出只出现一次的数字(在成对出现的数组中)。

4. 按位非(~)

原理:对操作数的每个位取反(0 变 1,1 变 0)。由于使用补码表示,~n 等于 -n - 1

示例

let a = 5;    // 二进制:0000 0000 0000 0000 0000 0000 0000 0101
let result = ~a; // 取反:1111 1111 1111 1111 1111 1111 1111 1010 → 十进制 -6
console.log(result); // 输出:-6

典型应用

  • 快速取负减一~n 等价于 -n - 1
  • 结合 indexOf 简化判断if (~str.indexOf("search")) 等价于 if (str.indexOf("search") !== -1),因为 indexOf 返回 -1 时,~-1 为 0(假值),其他情况为非零(真值)。

5. 左移(<<)

原理:将第一个操作数的所有位向左移动指定的位数,右侧空出的位补 0。左移 n 位相当于乘以 2^n。

示例

let a = 5;    // 二进制:0101
let result = a << 2; // 010100 → 十进制 20
console.log(result); // 输出:20 (5 * 2^2 = 20)

典型应用

  • 快速乘以 2 的幂:性能优于乘法(但现代 JavaScript 引擎的优化已不明显)。
  • 组合多个值到一个整数:常用于颜色值、IP 地址的编码。

6. 有符号右移(>>)

原理:将第一个操作数的所有位向右移动指定的位数,左侧空出的位用符号位(最高位)填充。右移 n 位相当于除以 2^n 并向下取整。

示例

let a = -20;   // 二进制补码表示:1111 1111 1111 1111 1111 1111 1110 1100
let result = a >> 2; // 右移两位:1111 1111 1111 1111 1111 1111 1111 1011 → 十进制 -5
console.log(result); // 输出:-5(-20 / 4 = -5)

典型应用

  • 快速除以 2 的幂(向下取整):对于正数和负数都适用。

7. 无符号右移(>>>)

原理:将第一个操作数的所有位向右移动指定的位数,左侧空出的位补 0。对于正数,结果与 >> 相同;对于负数,结果会变成很大的正数。

示例

let a = -20;   // 二进制补码:1111 1111 1111 1111 1111 1111 1110 1100
let result = a >>> 2; // 右移两位:0011 1111 1111 1111 1111 1111 1111 1011 → 十进制 1073741819
console.log(result); // 输出:1073741819

典型应用

  • 将负数转换为正数(但值会变化):通常用于处理二进制数据或颜色值,确保结果为非负整数。

典型应用场景实例

场景 1:权限控制

假设有三种权限:读(1 << 0)、写(1 << 1)、执行(1 << 2)。

const READ = 1 << 0;   // 1
const WRITE = 1 << 1;  // 2
const EXECUTE = 1 << 2;// 4

let userPermissions = 0;
// 授予读和写权限
userPermissions = userPermissions | READ | WRITE; // 3 (二进制 011)

// 检查是否有写权限
if (userPermissions & WRITE) {
    console.log("有写权限");
}

// 移除读权限
userPermissions = userPermissions & ~READ;

场景 2:颜色值处理(ARGB)

颜色值通常表示为 32 位整数,每 8 位表示一个通道(Alpha, Red, Green, Blue)。

function getAlpha(color) {
    return (color >>> 24) & 0xFF;
}
function getRed(color) {
    return (color >>> 16) & 0xFF;
}
// 设置绿色分量
function setGreen(color, green) {
    return (color & ~(0xFF << 8)) | ((green & 0xFF) << 8);
}
let color = 0xFF336699; // ARGB
console.log(getAlpha(color).toString(16)); // 输出:ff

场景 3:快速判断是否为 2 的幂

function isPowerOfTwo(n) {
    return n > 0 && (n & (n - 1)) === 0;
}
// 原理:2 的幂的二进制表示只有一个 1,n-1 会将该位变为 0,低位全变为 1,按位与结果为 0。

注意事项

  • 32 位限制:位运算只作用于 32 位整数,超出范围的位会被截断。
  • 性能考量:在现代 JavaScript 引擎中,位运算的性能优势已经不明显,除非在密集计算的场景(如图像处理、游戏)。可读性和正确性应优先。
  • 负数的处理:注意有符号右移和无符号右移的区别,尤其是在处理二进制数据时。

通过理解位操作符的原理和典型应用,你可以在需要底层操作或优化时,更有效地使用它们。

JavaScript 中的位操作符(Bitwise Operators)与典型应用场景 在 JavaScript 中,位操作符用于直接操作数值的二进制位。虽然 JavaScript 的数字都是双精度浮点数,但进行位运算时,会先将操作数转换为 32 位有符号整数(补码表示),执行运算,然后再转换回 64 位浮点数。这个过程对开发者是透明的。 位操作符包括: & (按位与 AND) | (按位或 OR) ^ (按位异或 XOR) ~ (按位非 NOT) << (左移) >> (有符号右移) >>> (无符号右移) 理解这些操作符的关键在于明白它们对二进制位的操作逻辑。 1. 按位与(&) 原理 :对两个操作数的每个对应位执行与操作,只有两个位都是 1 时,结果才为 1,否则为 0。 示例 : 典型应用 : 判断奇偶性 : (n & 1) === 0 表示 n 是偶数, (n & 1) === 1 表示 n 是奇数。 权限控制 :每个权限用一个二进制位表示,通过 & 检查是否具有某个权限。 提取特定位 :用掩码(mask)提取指定位。 2. 按位或(|) 原理 :对两个操作数的每个对应位执行或操作,只要有一个位是 1,结果就为 1。 示例 : 典型应用 : 组合权限 :将多个权限合并到一个值中。 设置特定位为 1 :使用掩码将指定位置 1。 3. 按位异或(^) 原理 :对两个操作数的每个对应位执行异或操作,如果两个位不同,结果为 1;相同则为 0。 示例 : 典型应用 : 交换两个变量的值(不用临时变量) : 简单的加密/解密 :用同一个密钥异或两次可还原数据。 找出只出现一次的数字 (在成对出现的数组中)。 4. 按位非(~) 原理 :对操作数的每个位取反(0 变 1,1 变 0)。由于使用补码表示, ~n 等于 -n - 1 。 示例 : 典型应用 : 快速取负减一 : ~n 等价于 -n - 1 。 结合 indexOf 简化判断 : if (~str.indexOf("search")) 等价于 if (str.indexOf("search") !== -1) ,因为 indexOf 返回 -1 时, ~-1 为 0(假值),其他情况为非零(真值)。 5. 左移(<<) 原理 :将第一个操作数的所有位向左移动指定的位数,右侧空出的位补 0。左移 n 位相当于乘以 2^n。 示例 : 典型应用 : 快速乘以 2 的幂 :性能优于乘法(但现代 JavaScript 引擎的优化已不明显)。 组合多个值到一个整数 :常用于颜色值、IP 地址的编码。 6. 有符号右移(>>) 原理 :将第一个操作数的所有位向右移动指定的位数,左侧空出的位用符号位(最高位)填充。右移 n 位相当于除以 2^n 并向下取整。 示例 : 典型应用 : 快速除以 2 的幂(向下取整) :对于正数和负数都适用。 7. 无符号右移(>>>) 原理 :将第一个操作数的所有位向右移动指定的位数,左侧空出的位补 0。对于正数,结果与 >> 相同;对于负数,结果会变成很大的正数。 示例 : 典型应用 : 将负数转换为正数(但值会变化) :通常用于处理二进制数据或颜色值,确保结果为非负整数。 典型应用场景实例 场景 1:权限控制 假设有三种权限:读(1 << 0)、写(1 << 1)、执行(1 < < 2)。 场景 2:颜色值处理(ARGB) 颜色值通常表示为 32 位整数,每 8 位表示一个通道(Alpha, Red, Green, Blue)。 场景 3:快速判断是否为 2 的幂 注意事项 32 位限制 :位运算只作用于 32 位整数,超出范围的位会被截断。 性能考量 :在现代 JavaScript 引擎中,位运算的性能优势已经不明显,除非在密集计算的场景(如图像处理、游戏)。可读性和正确性应优先。 负数的处理 :注意有符号右移和无符号右移的区别,尤其是在处理二进制数据时。 通过理解位操作符的原理和典型应用,你可以在需要底层操作或优化时,更有效地使用它们。