JavaScript位运算实用指南:0与1的运算哲学
位运算在JavaScript中是一种对数字的二进制位进行操作的技巧。虽然日常开发中不常用,但在处理权限控制、状态管理、性能优化等场景时非常有用。
位运算的基本概念
JavaScript中的位运算会将数字转换为32位二进制形式进行计算。如果是负数,会使用二进制补码表示。运算结束后,结果会转换回十进制数字返回。
数字的进制表示
JavaScript支持多种进制表示法:
let decimal = 42; // 十进制
let octal = 0o52; // 八进制,以0o开头
let hex = 0x2A; // 十六进制,以0x开头
let binary = 0b101010; // 二进制,以0b开头
console.log(binary.toString(2)); // "101010" - 转二进制
console.log(binary.toString(10)); // "42" - 转十进制二进制补码说明
计算机用补码表示负数。正数的补码就是其本身,负数的补码计算步骤:
取绝对值的二进制
所有位取反(0变1,1变0)
结果加1
例如-5的补码:
5的二进制:00000101
取反:11111010
加1:11111011
1. 按位与 (&)
对应位都为1时结果为1,否则为0。
let a = 12; // 二进制 1100
let b = 10; // 二进制 1010
console.log(a & b); // 8 (二进制 1000)
console.log((12).toString(2)); // "1100"
console.log((10).toString(2)); // "1010"
console.log((8).toString(2)); // "1000"实用场景:权限检查
// 定义权限
const READ = 1; // 0001
const WRITE = 2; // 0010
const EXECUTE = 4; // 0100
let userPermissions = READ | WRITE; // 0011
// 检查权限
function hasPermission(permissions, permission) {
return (permissions & permission) === permission;
}
console.log(hasPermission(userPermissions, READ)); // true
console.log(hasPermission(userPermissions, EXECUTE)); // false2. 按位或 (|)
对应位有1时结果为1,否则为0。
let a = 9; // 二进制 1001
let b = 3; // 二进制 0011
console.log(a | b); // 11 (二进制 1011)实用场景:权限添加
let permissions = READ; // 初始只有读权限
// 添加写权限
permissions = permissions | WRITE;
console.log(hasPermission(permissions, WRITE)); // true3. 按位异或 (^)
对应位不同时结果为1,相同时为0。
let a = 15; // 二进制 1111
let b = 6; // 二进制 0110
console.log(a ^ b); // 9 (二进制 1001)实用场景:切换状态
let settings = 0; // 所有设置关闭
// 切换夜间模式(第一位)
const NIGHT_MODE = 1;
settings = settings ^ NIGHT_MODE; // 开启
console.log(settings); // 1
settings = settings ^ NIGHT_MODE; // 关闭
console.log(settings); // 04. 按位非 (~)
所有位取反。
let a = 5; // 二进制 00000000000000000000000000000101
console.log(~a); // -6 (二进制 11111111111111111111111111111010)实用场景:数组查找的简写
let arr = [1, 2, 3, 4, 5];
// 传统写法
if (arr.indexOf(3) !== -1) {
console.log('找到元素');
}
// 使用位运算简写
if (~arr.indexOf(3)) {
console.log('找到元素');
}5. 左移 (<<)
二进制位向左移动,右边补0。
let a = 3; // 二进制 11
console.log(a << 2); // 12 (二进制 1100)
console.log(a << 4); // 48 (二进制 110000)实用场景:快速乘以2的幂
// 相当于乘以 2^n
console.log(5 << 1); // 10 (5 * 2^1)
console.log(5 << 2); // 20 (5 * 2^2)
console.log(5 << 3); // 40 (5 * 2^3)6. 有符号右移 (>>)
二进制位向右移动,左边用符号位填充。
let a = 16; // 二进制 10000
let b = -8; // 负数
console.log(a >> 2); // 4 (二进制 100)
console.log(b >> 1); // -4实用场景:快速除以2的幂
// 相当于除以 2^n 并向下取整
console.log(20 >> 1); // 10 (20 / 2^1)
console.log(20 >> 2); // 5 (20 / 2^2)
console.log(20 >> 3); // 2 (20 / 2^3)7. 无符号右移 (>>>)
二进制位向右移动,左边补0。
let a = -5; // 负数
console.log(a >>> 1); // 2147483645复合赋值运算符
每个位运算符都有对应的复合赋值形式:
let x = 15;
x &= 3; // x = x & 3
console.log(x); // 3
x |= 8; // x = x | 8
console.log(x); // 11
x ^= 4; // x = x ^ 4
console.log(x); // 15
x <<= 1; // x = x << 1
console.log(x); // 30
x >>= 2; // x = x >> 2
console.log(x); // 7实际应用案例
1. 状态管理系统
// 定义状态常量
const STATE_IDLE = 1; // 0001
const STATE_LOADING = 2; // 0010
const STATE_SUCCESS = 4; // 0100
const STATE_ERROR = 8; // 1000
class StateManager {
constructor() {
this.state = STATE_IDLE;
}
setState(newState) {
this.state |= newState;
}
clearState(stateToClear) {
this.state &= ~stateToClear;
}
hasState(checkState) {
return (this.state & checkState) === checkState;
}
toggleState(stateToToggle) {
this.state ^= stateToToggle;
}
}
// 使用示例
const manager = new StateManager();
manager.setState(STATE_LOADING);
console.log(manager.hasState(STATE_LOADING)); // true
manager.setState(STATE_SUCCESS);
console.log(manager.hasState(STATE_LOADING | STATE_SUCCESS)); // true
manager.clearState(STATE_LOADING);
console.log(manager.hasState(STATE_LOADING)); // false2. 颜色操作
// 从RGB值中提取颜色分量
function getRGBComponents(color) {
const red = (color >> 16) & 0xFF;
const green = (color >> 8) & 0xFF;
const blue = color & 0xFF;
return { red, green, blue };
}
// 合并RGB分量
function combineRGB(red, green, blue) {
return (red << 16) | (green << 8) | blue;
}
// 使用示例
const color = 0xFFA500; // 橙色
const components = getRGBComponents(color);
console.log(components); // {red: 255, green: 165, blue: 0}
const newColor = combineRGB(255, 200, 100);
console.log(newColor.toString(16)); // "ffc864"3. 奇偶判断
// 判断奇偶的快速方法
function isEven(num) {
return (num & 1) === 0;
}
console.log(isEven(4)); // true
console.log(isEven(7)); // false性能注意事项
虽然位运算通常很快,但在现代JavaScript引擎中,与普通算术运算的性能差异不大。选择使用位运算应该是为了代码的清晰度和特定功能需求,而不是单纯追求性能。
总结
位运算在JavaScript中提供了强大的二进制操作能力。通过理解和运用这些运算符,可以:
高效处理权限和状态
操作颜色值
进行快速的数学计算
实现紧凑的数据存储
掌握这些技巧能让你的代码在某些场景下更加简洁高效。建议在实际项目中根据需求合理使用,避免过度优化。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!