菜鸡日常写代码,发现了之前的大佬们写的>>、<<,当时我就不开心了。这是啥、我在哪、写的什么玩应。
![f9dda18836d290afe9c21fe4b22dd257.png](https://i-blog.csdnimg.cn/blog_migrate/0833864b7ad74cfcd20e7003fbb935b9.png)
所以没办法操起度娘和google仔细学习了一下相关的东西。发现这玩应还是有一点意思的,所以为了不被大佬吐槽。偷偷地记录学习一下。
![94662939f0c0c54154abd86762fd16d9.png](https://i-blog.csdnimg.cn/blog_migrate/c39a98d23df228734fff09a4728e9963.png)
首先js的位运算符简单介绍一下(网络截图,我是大自然的搬运工)
![aa2cf744b4ddc7ae66be0df60210e12a.png](https://i-blog.csdnimg.cn/blog_migrate/90075bf94e983c9e1cd00cca37e6b326.jpeg)
这些运算符看着有点乱。感觉好像很复杂的样子。还是通过输出能看明白点,首先说一下<<、>>这几个运算符。
![eee99ef15715429cedf96009d117170a.png](https://i-blog.csdnimg.cn/blog_migrate/b036c6268a3840a81fec08cb52d25f0e.jpeg)
![ba7e974c7e6eba1daf281e0eb64dc337.png](https://i-blog.csdnimg.cn/blog_migrate/e816a4558d603b3f31a78c49affc60de.png)
这里可以看出 实际上<< 这个运算符就是将二进制的符号向左移动,并且用0去填充,好吧,说得这么复杂,实际上就可以理解成 左边数字× 2右边数字 这样看来好像也不是很难。
![72a9d7995193c60fefd3c950e51c195d.png](https://i-blog.csdnimg.cn/blog_migrate/3da928dbe26d4644a6b25d43a0ae812b.jpeg)
![508e1629e7b3f74dd2796125edc83939.png](https://i-blog.csdnimg.cn/blog_migrate/a55c9c09792bea31013ed71d2333633f.png)
这里再看一下 >> 这个运算符就是与之前的完全相反的效果。向右移动,实际上就是之前的平方操作改成开平方操作。并向下取整而已。但是要注意的是如果前面的数字是负数的话,虽然也是开平方,但是它也是向下取整的,也就是说绝对值是会偏大的。
这样我们继续观察一下比较重要的&和|符号。我感觉这俩符号的存在使个位运算符的使用有了意义。
![05cd2d4d08380015c0d7fcbc0158f3f3.png](https://i-blog.csdnimg.cn/blog_migrate/2efe8e61982056d9d9fe62f69336ce00.jpeg)
![0d99d792fd6266a3d943286ccf0a8435.png](https://i-blog.csdnimg.cn/blog_migrate/18a268e62a2f38f97ad1a97b78142f31.png)
这样可以明显的看出来。| 运算符的作用主要是对比二进制时如果有一位为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。
![db3f6711900e114e5ca643ada5cec77a.png](https://i-blog.csdnimg.cn/blog_migrate/0e79e4b8231c987d13226e10629e5ca0.jpeg)
![cbe10bbbbb71690243444002e9c51901.png](https://i-blog.csdnimg.cn/blog_migrate/0ef55a4d03877c9f1e0738671faeec9c.png)
除此之外还有^和~符号没有说道,这两个符号可以作用于权限删除的时候去使用。例如使用^删除权限
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....这样的权限等级,如果不同的权限较多,那就需要所谓的权限空间了。就是说对于权限进行分类。再进行筛选使用。这样看还是挺有意思的。