JS中的位运算

· 3min · naeco

前言

最近在做项目,有个需求是消息置顶功能,类似于微信聊天里面的置顶。这个功能前端单独做也没问题,但我们需要多端统一状态,所以需要前后台的配合。所以后台需要在每个消息加一个字段表示是否置顶,但我翻文档并没有发现这个字段,后来我抓包发现置顶会返回一个 status 为 1063,而不置顶会返回 1059。后面和后台确认了一下才知道他们用 status 这个字段表示了好几种状态,每一个状态分别用二进制的一位来代表,置顶这个状态就用了第三位,所以同一个消息置顶和不置顶 status 的值会相差 4(2^2=4)。知道什么意思就好办了,嗯,首先先把 status 用toString(2)转化为二进制,然后再提取第三位来判断。等等,这样做实在太麻烦了,有没有简单一点的方法呢?有的,这时候位运算就派上用场了,我们只需要写一行代码就可以判断了:

  if ( (status & 4) !== 0 ) {
    ...
  }

&叫做按位与运算符,和&&很像,只有两个操作数的比特位都是 1 时才返回 1。所以只要第三位是 0,不管 status 有啥,与 4 进行按位与都会返回 0。同样的原理,我们让 status 分别和 2^(n-1)进行按位与,就可以提取出每一位的状态,这样用一个字段就可以表示全部的状态。 做完这个需求后,我又在网上看了一些文章,发现了位运算在 JS 中的一些妙用:

向下取整(1)

const n = 7.5;
Math.floor(n); // 7
7.5 | 0; // 7

向下取整(2)

const n = 7.5;
Math.floor(n); // 7
~~n; // 7

0 和 1 切换

0 ^ 1; // 0
1 ^ 1; // 1

乘法(左移一位相当于乘 2)

2 << 1; //4
3 << 1; //6
4 << 1; //8

后续

暂时想到的只有这么多,以后找到再补充。不过提醒一句,虽然位运算符看起来很简洁,但带来的是可读性的大大降低,再加上 JS 中奇怪的整型,我们很难保证不会出什么差错,所以建议减少使用。