位运算符 #

一、运算符概述 #

位运算符直接对整数的二进制位进行操作。在处理标志位、权限、颜色值等场景中非常有用。

二、二进制基础 #

2.1 二进制表示 #

typescript
// 十进制转二进制
console.log((10).toString(2)); // "1010"
console.log((255).toString(2)); // "11111111"

// 二进制字面量(ES6+)
const binary = 0b1010; // 10
console.log(binary); // 10

// 八进制字面量
const octal = 0o755; // 493
console.log(octal); // 493

// 十六进制字面量
const hex = 0xff; // 255
console.log(hex); // 255

2.2 32位整数 #

JavaScript位运算符将操作数视为32位整数:

typescript
// 正数:原码表示
// 5 = 00000000000000000000000000000101

// 负数:补码表示
// -5 = 11111111111111111111111111111011

三、按位与(&) #

3.1 基本用法 #

对应位都为1时结果为1,否则为0:

typescript
console.log(5 & 3); // 1

// 5 = 101
// 3 = 011
// -----
// 1 = 001

3.2 判断奇偶 #

typescript
function isEven(n: number): boolean {
  return (n & 1) === 0;
}

function isOdd(n: number): boolean {
  return (n & 1) === 1;
}

console.log(isEven(4)); // true
console.log(isOdd(5)); // true

3.3 权限检查 #

typescript
const PERMISSION_READ = 1;    // 001
const PERMISSION_WRITE = 2;   // 010
const PERMISSION_EXECUTE = 4; // 100

function hasPermission(userPermissions: number, permission: number): boolean {
  return (userPermissions & permission) === permission;
}

let userPermissions = PERMISSION_READ | PERMISSION_WRITE; // 3

console.log(hasPermission(userPermissions, PERMISSION_READ)); // true
console.log(hasPermission(userPermissions, PERMISSION_EXECUTE)); // false

3.4 掩码操作 #

typescript
// RGB颜色提取
const color = 0xffa500; // 橙色

const red = (color >> 16) & 0xff;
const green = (color >> 8) & 0xff;
const blue = color & 0xff;

console.log(red, green, blue); // 255, 165, 0

四、按位或(|) #

4.1 基本用法 #

对应位有一个为1时结果为1:

typescript
console.log(5 | 3); // 7

// 5 = 101
// 3 = 011
// -----
// 7 = 111

4.2 权限组合 #

typescript
const PERMISSION_READ = 1;
const PERMISSION_WRITE = 2;
const PERMISSION_EXECUTE = 4;

// 组合权限
const admin = PERMISSION_READ | PERMISSION_WRITE | PERMISSION_EXECUTE; // 7
const editor = PERMISSION_READ | PERMISSION_WRITE; // 3

console.log(admin); // 7
console.log(editor); // 3

4.3 向下取整 #

typescript
function toInt(n: number): number {
  return n | 0;
}

console.log(toInt(3.7)); // 3
console.log(toInt(-3.7)); // -3
console.log(toInt(3.14)); // 3

五、按位异或(^) #

5.1 基本用法 #

对应位不同时结果为1,相同时为0:

typescript
console.log(5 ^ 3); // 6

// 5 = 101
// 3 = 011
// -----
// 6 = 110

5.2 交换变量 #

typescript
let a = 5;
let b = 3;

a = a ^ b;
b = a ^ b;
a = a ^ b;

console.log(a, b); // 3, 5

5.3 简单加密 #

typescript
function xorEncrypt(text: string, key: number): string {
  let result = "";
  for (let i = 0; i < text.length; i++) {
    result += String.fromCharCode(text.charCodeAt(i) ^ key);
  }
  return result;
}

const original = "Hello";
const key = 42;

const encrypted = xorEncrypt(original, key);
console.log(encrypted); // 加密后的字符串

const decrypted = xorEncrypt(encrypted, key);
console.log(decrypted); // "Hello"

5.4 找出唯一数 #

typescript
function findSingle(nums: number[]): number {
  return nums.reduce((acc, num) => acc ^ num, 0);
}

console.log(findSingle([1, 2, 2, 1, 3])); // 3
console.log(findSingle([4, 1, 2, 1, 2])); // 4

六、按位非(~) #

6.1 基本用法 #

反转所有位:

typescript
console.log(~5); // -6

// 5 = 00000000000000000000000000000101
// ~5 = 11111111111111111111111111111010 (-6的补码)

6.2 公式 #

text
~x = -(x + 1)
typescript
console.log(~0); // -1
console.log(~1); // -2
console.log(~(-1)); // 0

6.3 检查元素是否存在 #

typescript
const arr = [1, 2, 3, 4, 5];

// indexOf返回-1表示不存在
// ~(-1) = 0 (假值)
if (~arr.indexOf(3)) {
  console.log("存在"); // 存在
}

if (!~arr.indexOf(6)) {
  console.log("不存在"); // 不存在
}

七、左移(<<) #

7.1 基本用法 #

所有位向左移动,右侧补0:

typescript
console.log(5 << 1); // 10

// 5 = 101
// 5 << 1 = 1010 = 10

7.2 乘以2的幂 #

typescript
console.log(5 << 1); // 10 (5 * 2)
console.log(5 << 2); // 20 (5 * 4)
console.log(5 << 3); // 40 (5 * 8)

// 公式:x << n = x * 2^n

7.3 颜色值组合 #

typescript
function rgbToHex(r: number, g: number, b: number): number {
  return (r << 16) | (g << 8) | b;
}

console.log(rgbToHex(255, 165, 0).toString(16)); // "ffa500"

八、右移(>>) #

8.1 有符号右移 #

保留符号位,向右移动:

typescript
console.log(10 >> 1); // 5

// 10 = 1010
// 10 >> 1 = 0101 = 5

console.log(-10 >> 1); // -5 (保留符号位)

8.2 除以2的幂 #

typescript
console.log(10 >> 1); // 5 (10 / 2)
console.log(10 >> 2); // 2 (10 / 4)
console.log(10 >> 3); // 1 (10 / 8)

// 公式:x >> n = Math.floor(x / 2^n)

8.3 无符号右移(>>>) #

用0填充左侧:

typescript
console.log(-1 >>> 0); // 4294967295 (32位最大值)
console.log(-1 >>> 1); // 2147483647

// 将有符号数转为无符号数
function toUnsigned(n: number): number {
  return n >>> 0;
}

console.log(toUnsigned(-1)); // 4294967295

九、位运算应用 #

9.1 标志位管理 #

typescript
const FLAG_A = 1 << 0; // 1
const FLAG_B = 1 << 1; // 2
const FLAG_C = 1 << 2; // 4
const FLAG_D = 1 << 3; // 8

class Flags {
  private flags: number = 0;
  
  set(flag: number): void {
    this.flags |= flag;
  }
  
  clear(flag: number): void {
    this.flags &= ~flag;
  }
  
  toggle(flag: number): void {
    this.flags ^= flag;
  }
  
  has(flag: number): boolean {
    return (this.flags & flag) === flag;
  }
  
  toString(): string {
    return this.flags.toString(2);
  }
}

const flags = new Flags();
flags.set(FLAG_A);
flags.set(FLAG_C);
console.log(flags.toString()); // "101"
console.log(flags.has(FLAG_A)); // true
console.log(flags.has(FLAG_B)); // false

flags.toggle(FLAG_B);
console.log(flags.toString()); // "111"

flags.clear(FLAG_A);
console.log(flags.toString()); // "110"

9.2 颜色操作 #

typescript
interface RGB {
  r: number;
  g: number;
  b: number;
}

function hexToRgb(hex: number): RGB {
  return {
    r: (hex >> 16) & 0xff,
    g: (hex >> 8) & 0xff,
    b: hex & 0xff
  };
}

function rgbToHex(rgb: RGB): number {
  return (rgb.r << 16) | (rgb.g << 8) | rgb.b;
}

const orange = 0xffa500;
console.log(hexToRgb(orange)); // { r: 255, g: 165, b: 0 }

const purple = rgbToHex({ r: 128, g: 0, b: 128 });
console.log(purple.toString(16)); // "800080"

9.3 位掩码 #

typescript
const MASK_LOW_BYTE = 0xff;
const MASK_HIGH_BYTE = 0xff00;

function getLowByte(value: number): number {
  return value & MASK_LOW_BYTE;
}

function getHighByte(value: number): number {
  return (value & MASK_HIGH_BYTE) >> 8;
}

const value = 0x1234;
console.log(getLowByte(value).toString(16)); // "34"
console.log(getHighByte(value).toString(16)); // "12"

9.4 快速数学运算 #

typescript
// 判断是否为2的幂
function isPowerOfTwo(n: number): boolean {
  return n > 0 && (n & (n - 1)) === 0;
}

console.log(isPowerOfTwo(4)); // true
console.log(isPowerOfTwo(6)); // false

// 向下取整到2的幂
function floorPowerOfTwo(n: number): number {
  let p = 1;
  while (p <= n) p <<= 1;
  return p >> 1;
}

console.log(floorPowerOfTwo(5)); // 4
console.log(floorPowerOfTwo(17)); // 16

// 绝对值(不用Math.abs)
function abs(n: number): number {
  const mask = n >> 31;
  return (n ^ mask) - mask;
}

console.log(abs(-5)); // 5
console.log(abs(5)); // 5

十、位运算符优先级 #

优先级 运算符 说明
1 ~ 按位非
2 << >> >>> 移位
3 & 按位与
4 ^ 按位异或
5 | 按位或
typescript
console.log(1 | 2 & 3); // 3 (&优先级高于|)
console.log((1 | 2) & 3); // 3

console.log(1 << 2 | 3); // 7 (<<优先级高于|)
console.log(1 << (2 | 3)); // 32

十一、总结 #

本章学习了:

  • 按位与(&)和权限检查
  • 按位或(|)和权限组合
  • 按位异或(^)和交换变量
  • 按位非(~)和取反
  • 左移(<<)和乘法
  • 右移(>>、>>>)和除法
  • 位运算实际应用
  • 运算符优先级

下一章,我们将学习控制流。

最后更新:2026-03-28