0%

js 位运算符

未运算符用于直接对二进制进行计算,一共有七个:

  • 或运算符(or): 符号为|
  • 与运算符(and):符号为&
  • 否运算符(not):符号为~
  • 左移运算符(left shift):符号为<<
  • 右移运算符(right shift):符号为>>
  • 带符号位的右移运算符(zero filled right shift):符号为>>> 位运算符直接处理每一个比特位(bit),是非常底层的运算,速度极快,缺点是不直观,许多场合不能使用它们。位运算符只对整数起作用。如果运算子不是整数,会自动转换为整数后再执行。

    JavaScript进制表示法

    先复习下JavaScript中进制的表示法,进制有:二进制、八进制、十进制、十六进制。
  • 二进制 表示二进制需要前缀0b,例如:0b100,等于4
  • 八进制 表示八进制需要前缀0,例如:022,表示18,八进制不可有8和9数字,否则会当十进制来计算。
  • 十进制 普通数字表示十进制
  • 十六进制 表示十六进制需要前缀0x,例如:0x22,表示34.

进制间的转换,十进制转换为其他进制:(number).toString(radix),括住数字才可以调用toString函数。其他进制转换为十进制:parseInt(string, radix),radix介于2~36之间。

虽然在JavaScript内部,数值都是以64位浮点数的形式存储,但是在做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。利用这一特性,可以将任何数值转换为32位整数:

1
2
3
function toInt32(x) {
return x | 0;
}

或运算符

或运算符|逐位比较两个运算子,两个二进制位中只要有一个为1,就返回1,否则返回0。
比如:6 | 4,6的二进制为110,4的二进制为10,所以他们的与运算的结果为110,还是6.

位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分。所以上面toInt32()这个方法也实现了向下取整。**注意:取整方法不适用于超过32位整数最大值2147483647的数。

与运算符

与运算符&逐位比较两个运算子的二进制位之中只要有一个位为0,就返回0,否则返回1.
比如:6 & 4,6的二进制为110,4的二进制为10,所以他们的与运算的结果为010,为4.

否运算

否运算~将没给二进制位都变为相反的值(0变1,1变0),它的返回结果比较复杂。

位运算时,JavaScript内部将所有的运算子都转为32位的二进制整数再进行运算。而32位整数的第一位是符号位。JavaScript内部采用补码方式表示负数,即需要将这个数减去1,再取一次反,然后加上符号,才能得到这个符号对应的10进制的值。
例如:3的32位整数形式是00000000000000000000000000000011,否运算后得到11111111111111111111111111111100,减去1得到11111111111111111111111111111011,再取一次反得到00000000000000000000000000000100,再加上负号得到-4,即~3 // = -4
简单记忆:一个数与自身的取反值相加,等于-1一个整数连续两次否运算,得到它自身。 ~~3 // 3

异或运算

异或运算^在两个二进制位不同时返回1,相同时返回0。例如0 & 3,3的二进制11和0的二进制00,运算后得到11,即3.

异或运算连续对两个数进行三次异或运算,可以互换他们的值:

1
2
3
var a = 10;
var b = 99;
a ^= b, b ^= a, a ^= b; // a = 99, b = 10

左移运算符

左移运算符<<表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以2的指定次方(最高位即符号位不参与移动)。例如:4 << 1,4的二进制为100,左移一位为1000,即8,相当于乘以2的1次方。

实例应用:rgb转hex

RGB是三通道颜色,相当于红绿蓝三个颜色通过不同的亮度,来组合为需要的颜色,0为最暗,255为最亮。

HEX是十六进制颜色,通过16进制0~F这16个字符来表达颜色,同样,000000位黑色,FFFFFF为白色。

RGB的三个通道的最大值为256,而256是16的平方,HEX为六位16进制的数字,每两位对应一个通道。即:

  • RGB (x, y, z)
  • HEX # aa bb cc

换句话说,RGB分别表示十进制的HEX,HEX表示16进制的RGB的一组数据。
将RGB转换为HEX,分别将RGB三个通道除以16,然后转化为十六进制,再拼在一块,就可以得到HEX。反之可以将HEX转换为RGB。使用左移运算符尝试下转换:

1
2
3
4
5
function rgb2hex (r, g, b) {
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).substr(1);
}
var color = {r: 186, g: 218, b: 85};
console.log(rgb2hex(color.r, color.g, color.b)); // #bada55

最前面加上(1<<24)的作用是为了保证结果是6位数。

然后看看逆转,从hex到rgb:

1
2
3
4
5
6
7
8
9
10
function hex2rgb(hex) {
const str = hex.substr(1);
const color = {r: 0, g: 0, b: 0};
color.r = ('0x' + str.substr(0, 2)) | 0;
color.g = ('0x' + str.substr(2, 2)) | 0;
color.b = ('0x' + str.substr(4, 2)) | 0;
return color;
}
var hex = '#bada55';
console.log(hex2rgb(hex)); # { r: 186, g: 218, b: 85 }

右移运算符

右移运算符(>>)表示将一个数的二进制向右移动指定的位数,头部补0,即除以2的指定次方(最高位即符号位不参与移动)。例如:4 >> 1,4的二进制为10,右移一位为01,即2.

右移运算可以模拟2的整除运算。

1
2
5 >> 1 // 2
0xb >> 2 // 2, 11 / 2

带符号位的右移运算符

带符号的右移运算符(>>>)表示将一个数的二进制形式向右移动,包括符号位也参与移动,头部补0,所以该值总是得到正值。区别主要在负数(用在负数上也没啥意义,就不做例子了)。这个运算符的作用实际上是将一个值转为32位无符号整数。查看一个负整数在计算机内部的存储形式,最快的方法就是使用这个运算符。

参考文档:http://javascript.ruanyifeng.com/grammar/operator.html#toc27

码字辛苦,打赏个咖啡☕️可好?💘