JavaScript位运算实用指南:0与1的运算哲学

更新日期: 2025-10-12阅读: 33标签: 运算

位运算在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"    - 转十进制


二进制补码说明

计算机用补码表示负数。正数的补码就是其本身,负数的补码计算步骤:

  1. 取绝对值的二进制

  2. 所有位取反(0变1,1变0)

  3. 结果加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)); // false


2. 按位或 (|)

对应位有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)); // true


3. 按位异或 (^)

对应位不同时结果为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); // 0


4. 按位非 (~)

所有位取反。

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)); // false

2. 颜色操作

// 从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中提供了强大的二进制操作能力。通过理解和运用这些运算符,可以:

  • 高效处理权限和状态

  • 操作颜色值

  • 进行快速的数学计算

  • 实现紧凑的数据存储

掌握这些技巧能让你的代码在某些场景下更加简洁高效。建议在实际项目中根据需求合理使用,避免过度优化。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/article/detial/12994

js除了Math.floor方法,还可以通过位运算|,>>实现向下取整

我们都知道通过Math.floor()方法可实现数值的向下取整,得到小于或等于该数字的最大整数。除了Math.floor方法,还可以使用位运算|,>>来实现向下取整哦

es6 扩展运算符 三个点(...)

扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

巧用JS位运算

位运算的方法在其它语言也是一样的,不局限于JS,所以本文提到的位运算也适用于其它语言。位运算是低级的运算操作,所以速度往往也是最快的

js中使用位运算,让执行效率更高

平常的数值运算,其本质都是先转换成二进制再进行运算的,而位运算是直接进行二进制运算,所以原则上位运算的执行效率是比较高的,由于位运算的博大精深,下面通过一些在js中使用位运算的实例

js各种取整方式及方法_四舍五入、向上取整、向下取整

js实现:四舍五入、向上取整、向下取整等方法。parseInt、Math.ceil、Math.round、Math.floor、toFixed等的使用

JavaScript循环计数器

JS经常会遇到延迟执行的动作,并且失败后自动尝试,尝试N次之后就不再尝试的需求,今天刚好又遇到,于是写个闭包,以后不断完善继续复用。检查并计数第一个参数用来标记是尝试哪个动作的,第二个参数是最大尝试次数

js 位运算符_js按位运算符及其妙用

大多数语言都提供了按位运算符,恰当的使用按位运算符有时候会取得的很好的效果。在我看来按位运算符应该有7个:& 按位与、| 按位或、^ 按位异或、~ 按位非

PHP取整、四舍五入取整、向上取整、向下取整、小数截取

PHP取整数函数常用的四种方法:1.直接取整,舍弃小数,保留整数:intval(); 2.四舍五入取整:round(); 3.向上取整,有小数就加1:ceil(); 4.向下取整:floor()。

JavaScript 中的相等操作符 ( 详解 [] == []、[] == ![]、{} == !{} )

ECMAScript 中的相等操作符由两个等于号 ( == ) 表示,如果两个操作数相等,则返回 true。相等操作符会先转换操作数(通常称为强制转型),然后比较它们的相等性。

关于js开发中保留小数位计算函数(以向上取整或向下取整的方式保留小数)

前端工作中经常遇到数字计算保留小数问题,由于不是四舍五入的方式不能使用toFixed函数,本文采用正则表达式匹配字符串的方式,解决对数字的向上或向下保留小数问题:

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!