玩转 js 位运算
今天突然看了一下js的位运算,发现这个东西挺有意思的,稍微尝试了一下各个场景,简单说一下这个东西吧。
首先js的位运算符简单介绍一下(网图)
这些运算符看着有点乱。感觉好像很复杂的样子。还是通过输出能看明白点,首先说一下<<、>>、>>>这三个运算符。
这里可以看出 实际上<< 这个运算符就是将二进制的符号向左移动,并且用0去填充,好吧,说得这么复杂,实际上就可以理解成 左边数字× 2右边数字 这样看来好像也不是很难。
这里再看一下 >> 这个运算符就是与之前的完全相反的效果。向右移动,实际上就是之前的平方操作改成开平方操作。并向下取整而已。但是要注意的是如果前面的数字是负数的话,虽然也是开平方,但是它也是向下取整的,也就是说绝对值是会偏大的。
这样我们再看一下另外的比较重要的&和|符号。我感觉这俩符号的存在使这个位运算符的使用有了意义。
这样可以明显的看出来。| 运算符的作用主要是对比二进制时如果有一位为1那就结果为1,&的作用是必须都为1则为1,反之为0。
简单看了一下网上诸多大佬的帖子,大概想了一下使用的场景。大概有如下场景
1、判断奇偶 这个还是挺有用的。毕竟前端经常会有列表展示,隔一行一个效果。这种就需要判断奇偶了。这种代码的原理是将二进制数字前面所有的位数全部清零,只需要判断最后一位数字是1还是0就可以判断奇偶了
function test(num) { return !!(num&1); // true为奇数,false为偶数 }
2、权限系统 这个的使用还是很有意思的,在linux系统中的修改权限问题的命令中 chmod 777 文件 其中7代表了可读可写可执行的文件。实际上我们也可以实现一个例如这个东西。
let r = 0b100 let w = 0b010 let x = 0b001 // 给用户赋 r w 两个权限 let user = r | w // user = 6 // user = 0b110 (二进制) console.log(!!(user & r)) // true 有 r 权限 console.log(!!(user & w)) // true 有 w 权限 console.log(!!(user & x)) // false 没有 x 权限
那么这个原理是什么呢?如下面两个图可以对比出,实际上判断权限的时候如果没有权限就会返回0000这样其实就是0,也就是false。
除此之外还有^和~符号没有说道,这两个符号可以作用于权限删除的时候去使用。例如使用^删除权限
let r = 0b100 let w = 0b010 let x = 0b001 let user = 0b110 // 有 r w 两个权限 // 执行异或操作,删除 r 权限 user = user ^ r console.log(!!(user & r)) // false 没有 r 权限 console.log(!!(user & w)) // true 有 w 权限 console.log(!!(user & x)) // false 没有 x 权限 console.log(user.toString(2).padStart(4, '0')) // 现在 user 是 0b010 // 再执行一次异或操作 user = user ^ r console.log(!!(user & r)) // true 有 r 权限 console.log(!!(user & w)) // true 有 w 权限 console.log(!!(user & x)) // false 没有 x 权限 console.log(user.toString(2).padStart(4, '0')) // 现在 user 又变回 0b110
由上面的内容可知这个实际上是有问题的。如果操作了两次就会导致权限恢复。那么我们如何只删除不增加呢?
let r = 0b100 let w = 0b010 let x = 0b001 let user = 0b110 // 有 r w 两个权限 // 删除 r 权限 user = user & (~r) console.log(!!(user & r)) // false 没有 r 权限 console.log(!!(user & w)) // true 有 w 权限 console.log(!!(user & x)) // false 没有 x 权限 console.log(user.toString(2).padStart(4, '0')) // 现在 user 是 0b010 // 再执行一次 user = user & (~r) console.log(!!(user & r)) // false 没有 r 权限 console.log(!!(user & w)) // true 有 w 权限 console.log(!!(user & x)) // false 没有 x 权限 console.log(user.toString(2).padStart(4, '0')) // 现在 user 是 0b010
由于权限的控制是依靠位运算,也就是说实际上1、2、4、8....这样的权限等级,如果不同的权限较多,那就需要所谓的权限空间了。就是说对于权限进行分类。再进行筛选使用。这样看还是挺有意思的。