什么是位运算?

位运算是在数字底层(即表示数字的 32 个数位)进行运算的。由于位运算是低级的运算操作,所以速度往往也是最快的(相对其它运算如加减乘除来说),并且借助位运算有时我们还能实现更简单的程序逻辑,缺点是很不直观,许多场合不能够使用。

js位运算符总共分为两类:逻辑位运算符:位与(&)、位或(|)、位异或(^)、非位(~)移位运算符:左移(<<)、右移(>>)、全右移(>>>)

  • 逻辑运算符
  1. 位与(&): 真真为真(1),其余为假(0)

var a = 1; var b = 2; console.log(a & b) 123

计算的过程如下:首先会把a 和 b 的值都转成二进制的数据(这里转换的数据是32的二进制哦),然后进行运算

js实例知识点 重温js位运算(1)

注意: 位运算 与 可以用于 b 中是否包含 a ,这个包含是指的是二进制的数据是否包含交集,具体的表达式如下: (a & b) === a

  1. 位或(|): 假假为假(0),其余为真(1)

var a = 1, b = 2; console.log(a | b) 12

计算过程如下:

js实例知识点 重温js位运算(2)

注意: 这个功能一般常用来取两个二进制数据的并集

  1. 位异或(^):相同为假(0),不同为真(1)

var a = 1, b = 3; console.log(a ^ b)

运算过程如下:

js实例知识点 重温js位运算(3)

注意: 异或运算一般可以用于做减法,通过更大的那个值来除去那个小的值,还剩多少

  1. 非位(~):真为假,假为真

var num = 1; var num1 = ~num; console.log(~num1 )

js存储的的负数一般要经过以下步骤,才可以进行存储。

将真码变成反码, 就是说把所有的 0 都变成1

把反码变成补码, 就是说在反码的基础上加1,然后这个表示的才是一个存储的数据,当拿来运算的时候,需要逆向转换, 先减1,返回在取反

我们知道,js中的数字默认是有符号的。有符号的32位二进制的最高位也就是第一位数字代表着正负,1代表负数,0代表整数。那到底11111111111111111111111111111110等于多少呢?最高位为1代表负数,负数的二进制转化为十进制:符号位不变,其他位取反加1。取反之后为10000000000000000000000000000001,加1之后为10000000000000000000000000000010,十进制为-2。

注意:这个运算符的妙用可以使用在 判断值是否为-1上,例如:const filters = ['aa', 'bb', 'c']; if (~filters.indexOf(a)) {} 而不是 if( filters.indexOf(a) != -1 ) or if( filters.indexOf(a) >= 0), 如果取一个数字的整数,可以直接使用~~数字

这里还有一个计算非运算的技巧:取非运算的时候,先把数据前面加一个负号, 然后在减1

js实例知识点 重温js位运算(4)

  • 移位运算符
  1. 左移(<<):首位符号为不动,把32位二进制数字整体往左边移动指定位数,左边超出部分被舍去,右边补0

9二进制有符号左移5位 9<<5 0000000000000000 0000000000001001 ------ 0000000000000000 0000000100100000

公式:数字1 × 2 ^ 数字2

计算机内是这样位移计算的,实际应用计算我们可以通过公式:num * (2^n) ,即:9*Math.pow(2,5)

  1. 右移(>>):首位符号为不动,把32位二进制数字整体往右边移动指定位数,右边超出部分被舍去,左边补0,这可能会丢失数据。

3二进制有符号右移5位 3>>1 0000000000000000 0000000000000011 ------ 0000000000000000 0000000000000001 12345

公式:取整(数字1 / 2 ^ 数字2)

js实例知识点 重温js位运算(5)

  1. 无符号右移(>>>):符号为也跟着一起移动,这样,无符号右移会把负数的二进制当成整数的二进制码
案列

// 运用场景,想要实现一个权限控制

enum Permission { Read = 1, Write = 2, Create = 4, Delete = 8 } let p: Permission = Permission.Read | Permission.Write; function hasPermission(target: Permission, per: Permission) { return (target & per) === per; } p = p ^ Permission.Write; console.log(hasPermission(p, Permission.Write));

,