玩转 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....这样的权限等级,如果不同的权限较多,那就需要所谓的权限空间了。就是说对于权限进行分类。再进行筛选使用。这样看还是挺有意思的。

  

原文地址:https://www.cnblogs.com/acefeng/p/13163964.html