常用的7个位运算符,以及在JS中的妙用

  • 位运算直接对二进制位进行计算,位运算直接处理每一个比特位,是非常底层的运算,好处是速度极快,缺点是很不直观,许多场合不能够使用。
  • 位运算只对整数起作用,如果一个运算数不是整数,会自动转为整数后再运行。
  • 在JavaScript内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。

JS中常用的7个位运算符

按位与(AND) &

&以特定的方式组合操作二进制数中对应的位,如果对应的位都为1,那么结果就是1, 如果任意一个位是0 则结果就是0。

1的二进制表示为: 00000000 00000000 00000000 00000001
3的二进制表示为: 00000000 00000000 00000000 00000011

console.log(1 & 3) // 1

按位或(OR) |

| 运算符跟 & 的区别在于如果对应的位中任一个操作数为1 那么结果就是1。

1的二进制表示为: 00000000 00000000 00000000 00000001
3的二进制表示为: 00000000 00000000 00000000 00000011

console.log(1 | 3) // 3

按位异或(XOR) ^

^ 如果对应两个操作位有且仅有一个1时结果为1,其他都是0。

1的二进制表示为: 00000000 00000000 00000000 00000001
3的二进制表示为: 00000000 00000000 00000000 00000011
2的二进制表示为: 00000000 00000000 00000000 00000010

console.log(1 ^ 3) // 2

按位非(NOT) ~

~ 运算符是对位求反,1变0, 0变1,也就是求二进制的反码。

1的二进制表示为: 00000000 00000000 00000000 00000001 3的二进制表示为: 00000000 00000000 00000000 00000011 1反码二进制表示: 11111111 11111111 11111111 11111110

简单记忆:一个数与自身的取反值相加等于-1

左移(Left shift)«

« 运算符使指定值的二进制数所有位都左移指定次数,其移动规则:丢弃高位,低位补0即按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。

1的二进制表示为: 00000000 00000000 00000000 00000001 2的二进制表示为: 00000000 00000000 00000000 00000010

console.log(1 << 1) // 2

有符号右移»

>> 该操作符会将指定操作数的二进制位向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。由于新的最左侧的位总是和以前相同,符号位没有被改变。所以被称作“符号传播”。

1的二进制表示为: 00000000 00000000 00000000 00000001 0的二进制表示为: 00000000 00000000 00000000 00000000

console.log(1 >> 1) // 0

无符号右移>>>

>>>该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符号位变成了 0,所以结果总是非负的。(译注:即便右移 0 个比特,结果也是非负的。)对于非负数,有符号右移和无符号右移总是返回相同的结果。例如, 9 »> 2 得到 2 和 9 » 2 相同。

位运算符在js中妙用

使用~, », «, >>>, |来取整

console.log(~~ 6.83)
console.log(6.83 >> 0)
console.log(6.83 << 0)
console.log(6.83 | 0) => > 浮点数不支持位运算,所以会先把1.1转成整数1再进行位运算 console.log(6.83 >>> 0) => >>>不可对负数取整

使用&, », |来完成rgb值和16进制颜色值之间的转换


/*** 16进制颜色值转RGB* 
@param {String} hex 16进制颜色字符串* 
@return {String} RGB颜色字符串*/

function hexToRGB(hex) {
  var hexx = hex.replace('#', '0x');
  var r = hexx >> 16;
  var g = hexx >> 8 & 0xff;
  var b = hexx & 0xff;
  return `rgb(${r}, ${g}, ${b})`
}

/*** RGB颜色转16进制颜色* 
@param {String} rgb RGB进制颜色字符串*
@return {String} 16进制颜色字符串*/

function RGBToHex(rgb) {
  var rgbArr = rgb.split(/[^\d]+/);
  var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3];
  return '#'+ color.toString(16)
}
// -------------------------------------------------
hexToRGB('#ffffff')   // 'rgb(255,255,255)'
RGBToHex('rgb(255,255,255)')   // '#ffffff'参考

调换两个数字的值

  1. 常规方法

     var num1 = 1, num2 = 2, temp;
     temp = num1;
     num1 = num2; // 2
     num2 = temp; // 1
    
  2. 位运算

     // 方法一
     var num1 = 1, num2 = 2;
     num1 = [num2, num2 = num1][0];
     console.log(num1); // 2
     console.log(num2); // 1
     // 方法二
     var num1 = 1, num2 = 2;
     num1 ^= num2; // num1 = num1 ^ num2 = 1 ^ 2 = 3
     num2 ^= num1; // num2 = num2 ^ (num1 ^ num2) = 2 ^ (1 ^ 2) = 1
     num1 ^= num2; // num1 = num1 ^ num2 = 3 ^ 1 = 2
     console.log(num1); // 2
     console.log(num2); // 1
    

判断奇数偶数

  1. 余数判断:

     function assert(n) {
       if (n % 2 === 1) {
         console.log("n是奇数");
       } else {
         console.log("n是偶数");
       }
     }
     assert(3);  // "n是奇数"
    
  2. 按位&判断:

    奇数的二进制码的最后一位数肯定是1,而1只有最后一位为1,按位&操作之后,结果肯定只有最后一位数为1。
    偶数的二进制表示的最后一位数是0,和1进行按位&操作,结果所有位数都为0。

     function assert(n) {
       if (n & 1) {
         console.log("n是奇数");
       } else {
         console.log("n是偶数");
       }
     }
     assert(3);  // "n是奇数"
    

2的n次方

function power(n) {
    return 1 << n;
}
power(5); // 32

二分之一

64 >> 1; // 32

相关参考

按位操作符 / MDN web docs

运算符 / 阮一峰