小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
最近跟我们公司后台做一个项目,发现了一个好玩的东西哈,真的以前没想到的,也有可能是我们太笨了,哈哈哈哈。不过现在用到也不晚,可能是老技术了,我也不知道,知道的人可以跟我说一下,是不是以前的人都是这样用的。
那这个是什么技术呢!!!它就是利用进制位运算来做用户的权限管理。非常好用,下面我分三个议题来讲。
- javaScript的进制位运算
- 权限的判断
- 用后感
一· 进制的位运算
我在用这个位运算的时候也是绞尽脑汁想了一天,最后发现使用的方法很简单,因为js已经帮你集成好了用法,这让我们用起来会更加方便。我是那种用一种技术就必须搞明白原理的人,不然不清不楚用一种技术,后期定位问题也很难,所以希望大家也是一样的。位运算我脑补了很多资料,看了很多博客的资料。
废话不多说,直接整起。。。。
1. JavaScript 位运算
1.1. Number
在讲位运算之前,首先简单看下 JavaScript
中的 Number
,下文需要用到。
在 JavaScript
里,数字均为基于 IEEE 754
标准的双精度 64 位的浮点数,引用某乎的图片,它的结构长这样:
sign bit(符号): 用来表示正负号
exponent(指数): 用来表示次方数
mantissa(尾数): 用来表示精确度
也就是说一个数字的范围只能在 -(2^53 -1) 至 2^53 -1
之间。
在此之外还有四种数字进制,有些进制是我们与计算机沟通的最终形态:
四种数字进制分别为:十进制、十六进制、八进制、二进制。
- 十进制:没有前导0的数值。这个也是我们经常用到
- 八进制:有前缀
0o
或0O
的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。 - 十六进制:有前缀
0x
或0X
的数值。 - 二进制:有前缀
0b
或0B
的数值。
下面是一些例子。
// 十进制
123456789
0
// 二进制:前缀 0b,0B
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607
// 八进制:前缀 0o,0O(以前支持前缀 0)
0o755 // 493
0o644 // 420
// 十六进制:前缀 0x,0X
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF // 81985529216486900
0XA // 10
我们 JavaScript
的 Number
就讲这么多。想了解更多的可以去看百度维基百科
1.2. 位运算
w3c是这么解释javasCript 位运算的:
简单来说就是:按位操作符将其操作数当作 32 位的比特序列(由 0 和 1 组成)操作,返回值依然是标准的 JavaScript
数值。
JavaScript
中位运算操作符有
运算符 | 用法 | 描述 | 按位与(AND) | a & b | 对于每一个比特位,只有两个操作数相应的比特位都是 1 时,结果才为 1,否则为 0。 | 按位或(OR) | a | b | 对于每一个比特位,当两个操作数相应的比特位至少有一个 1 时,结果为 1,否则为 0。 | 按位异或(XOR) | a ^ b | 对于每一个比特位,当两个操作数相应的比特位有且只有一个 1 时,结果为 1,否则为 0。 | 按位非(NOT) | ~a | 反转操作数的比特位,即 0 变成 1,1 变成 0。 | 左移(Left shift) | a << b | 将 a 的二进制形式向左移 b (< 32) 比特位,右边用 0 填充。 | 有符号右移 | a >> b | 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。 | 无符号右移 | a >>> b | 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。 |
---|
下面通过一些实例来加深对位运算的理解。
1.2.1 按位与(&)
&&运算符我们都知道,只有两个都为真,结果才为真。&道理是一样的,只有两个数的值为1时,才返回1。例如1和3的按位与操作:
0001
& 0011
---------
0001
只有对应的数为1时,结果才为1,其他都为0。
判断一个数是奇数还是偶数,我们会用求余数来判断:
function assert(n) {
if (n % 2 === 1) {
console.log("n是奇数");
} else {
console.log("n是偶数");
}
}
assert(3); // "n是奇数"
我们也可以用一个数和1进行按位&操作来判断,而且速度更快:
function assert(n) {
if (n & 1) {
console.log("n是奇数");
} else {
console.log("n是偶数");
}
}
assert(3); // "n是奇数"
下面是位运算过程:
1 = 0001
3 = 0011
--------
& = 0001
奇数的二进制码的最后一位数肯定是1,而1只有最后一位为1,按位&操作之后,结果肯定只有最后一位数为1。而偶数的二进制表示的最后一位数是0,和1进行按位&操作,结果所有位数都为0。
1.2.2 按位或(|)
|与||操作符的道理也是一样的,只要两个数中有一个数为1,结果就为1,其他则为0。
0001
| 0011
---------
0011
对浮点数向下求整,我们会用下面的方法:
var num = Math.floor(1.1); // 1
我们也可以用位运算来求整:
var num = 1.1 | 0; // 1
其实浮点数是不支持位运算的,所以会先把1.1转成整数1再进行位运算,就好像是对浮点数向下求整。所以1|0的结果就是1。
1.2.3 按位非(~)
按位非就是求二进制的反码:
var num = 1; // 二进制 00000000000000000000000000000001
var num1 = ~num; // 二进制 11111111111111111111111111111110
我们知道,js中的数字默认是有符号的。有符号的32位二进制的最高位也就是第一位数字代表着正负,1代表负数,0代表整数。那到底11111111111111111111111111111110
等于多少呢?最高位为1代表负数,负数的二进制转化为十进制:符号位不变,其他位取反加1。取反之后为10000000000000000000000000000001
,加1之后为10000000000000000000000000000010
,十进制为-2。
1.2.4 按位异或(^)
按位异或是两个数中只有一个1时返回1,其他情况返回0。
0001
^ 0011
---------
0010
数字与数字本身按位异或操作得到的是0,因为每两个对应的数字都相同,所以最后返回的都是0。
我们经常会需要调换两个数字的值:
var num1 = 1, num2 = 2, temp;
temp = num1;
num1 = num2; // 2
num2 = temp; // 1
如果装逼一点的话,可以这样:
var num1 = 1, num2 = 2;
num1 = [num2, num2 = num1][0];
console.log(num1); // 2
console.log(num2); // 1
如果想再装的稳一点的话,可以这样:
var num1 = 1, num2 = 2;
num1 ^= num2; // num1 = num1 ^ num2 = 1 ^ 2 = 3
num2 ^= num1; // num2 = num2 ^ (num1 ^ num2) = 2 ^ (1 ^ 2) = 1
num1 ^= num2; // num1 = num1 ^ num2 = 3 ^ 1 = 2
console.log(num1); // 2
console.log(num2); // 1
结束但又没有完全结束
东西有点多,这一篇我们暂时先说到这里,还没结束,下一篇我们会继续讲。感兴趣的小伙伴可以留意一下。
创作不易,请多多支持,点点赞、点点关注与收藏,就是对我最大的支持,感谢观看我的文章,这里是小小切图仔_可笑可笑
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!