JS中的位操作在实际项目中的应用
前言:
Linux中的文件管理子系统的权限管理,想必大家都知道:rwx分别代表read(可读),write(可写), execute(可执行,如果是可执行程序的话),其中rxw可以按照数字表示:
r ------------- 4
w ------------- 2
x ------------- 1
如果有可读,可写,可执行权限,则用7表示...
在最近的项目中,就遇到了这样的问题:我们做是IOT的硬件报警设备,现在一共有7种报警类型,每种设备报警的可能有:1种,多种或者0种,后台返回一个10进制数字来表示这种可能,前端需要根据后台返回的数字判断包含的报警。
其实这个就跟linux文件权限一样,后台用bit位来存储设备报警结果,一共有7种报警类型,8个bit位就够了,每一个bit位对应一种报警类型,如果包含某种报警,对应的位置为1,反之置为0,然后后台将bit转位10进制的数字传给前端。其实表示这7种报警类型常规的做法是:后台为这报警类型alarm字典,将这7种报警类型存入alarm字典中,每一种报警类型是否包含的话用true和false处理,返回给前端的话如下:
{ alarm1: true, alarm2: false, alarm3: true, alarm4: false, alarm5: true, alarm6: false, alarm7: true, }
从结果中,前端可以判定设备产生了4中报警:alarm1,alarm3,alarm5,alarm7。。。
回到我现在的问题中去,前端需要将后台返回的10进制数字转为2进制数字(8个bit位),然后去判断1的位置,如果某一位的值为1,则包含对应的报警.
方法一:非CS专业出身笨办法
let type = alarm.toString(2).padStart(8, '0').split('').reverse() const arr = [] // 用来存储包含的报警类型 for (var i = 0; i < type.length; i++) { if (type[b] === '1') { switch (i) { case 0: alarm.push[i] break case 1: alarm.push[i] break case 2: alarm.push[i] break case 3: alarm.push[i] break case 4: alarm.push[i] break case 5: alarm.push[i] break default: break } } } console.log(arr.toString()) // 打印出所有的报警类型
方法二:利用位操作判断(对于js按位操作不熟悉的同学,请自行补充相关知识)
const arr = [] // 用来存储包含的报警类型 for (let i = 0; i < 7; i++) { if (alarm >> i & 1) { arr.push(i) } } console.log(arr.toString()) // 打印出所有的报警类型
按照这个实现,虽然看着舒服,但是简洁加执行效率高,还是很帅的。
最后来说下,我google的实现结果,感觉更好理解:
// 预先定义不同报警类型 const alarm1 = 1; // 0000 0001 const alarm2 = 1 << 1; // 0000 0010 const alarm3 = 1 << 2; // 0000 0100 const alarm4 = 1 << 3; // 0000 1000 const alarm5 = 1 << 4; // 0001 0000 const alarm6 = 1 << 5; // 0010 0000 const alarm7 = 1 << 6; // 0100 0000 const arr = [] // 用来存储包含的报警类型 const alarm = 7; // 后台返回的10进制数字 // 是否包含alarm1 if (alarm & alarm1) {} // 是否包含alarm1和alarm2中的任意一个 if (alarm & (alarm1 | alarm2)) {} // 是否只包含alarm1和alarm2 if (alarm === (alarm1 | alarm2)) {} // 是否同时包含alarm1和alarm2 if (alarm === (alarm | (alarm1 | alarm2)) ) {}
参考资料:
https://codeburst.io/using-javascript-bitwise-operators-in-real-life-f551a731ff5