JavaScript通过位运算进行状态控制

位运算

按位与&

对每对比特位执行与(AND)操作。只有 a 和 b 都为1时,a & b 就是 1。如下表9 & 3 = 1

9=1001
3=0011
1=0001

由上表我们可以清晰的看出按位与的计算规则,由此可以引出一系列应用场景

判断奇偶

我们知道奇数的二进制最后一位必然为1,所以任意一个奇数 & 1 一定等于1。

// 判断奇偶
return number & 1 === 1

按位或 |

对每对比特位执行与(AND)操作。只有 a 和 b 任意一位为1时,a | b 就是 1。如下表9 | 3 = 11

9=1001
3=0011
11=1011

取整

对于一般的整数,返回值不会有任何变化。对于大于2的32次方的整数,大于32位的数位都会被舍去。

function toInt(num) {
    return num | 0
}
console.log(toInt(1.8))        // 1
console.log(toInt(1.23232))    // 1

按位非 ~

对每一个比特位执行非(NOT)操作。NOT a 结果为 a 的反转(即反码)。

ps: 对任一数值 x 进行按位非操作的结果为 -(x + 1)。例如,~5 结果为 -6:

负数存储采用的形式是二进制补码。计算数字二进制补码的步骤有三步:

1.确定该数字的非负版本的二进制表示(例如,要计算 -18的二进制补码,首先要确定 18 的二进制表示)

2.求得二进制反码,即要把 0 替换为 1,把 1 替换为 0(相当于~操作)

3.在二进制反码上加 1

我们可以看到一个数a取负相当于 ~a + 1, 即 -a = ~a + 1, 因此~a = -(a + 1)

应用场景:

取整 (位运算花样取整)

~~(-5.88) // -5

判断数组中某项是否存在

// 常用判断
if (arr.indexOf(item) > -1) {
    // code
}
// 按位非    ~-1 = - (-1 + 1)
if (~arr.indexOf(item)) {
    // code
}

按位异或 ^

对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。

其运算法则相当于不带进位的二进制加法

9=1001
3=0011
10=1010

应用场景:

切换变量0和1

假如我们通过某个条件来切换一个值为0或者1

function update(toggle) {
    num = toggle ? 1 : 0;
}

update(true);


// 通过异或我们可以这么写
num = num ^ 1;

交换两个变量的值(不用第三个变量)

let a = 5,
    b = 6;

a = a ^ b;
b = a ^ b;
a = a ^ b;

// 还可以通过运算
a = a + b;
b = a - b;
a = a - b;

// es 6
[a, b] = [b, a]

原理剖析:a = a ^ b; b = a ^ b 相当与 b = a ^ b ^ b = a ^ (b ^ b) = a ^ 0 = a;

按位移动操作符

按位移动操作符有两个操作数:第一个是要被移动的数字,而第二个是要移动的长度。移动的方向根据操作符的不同而不同。

按位移动会先将操作数转换为大端字节序顺序(big-endian order)的32位整数,并返回与左操作数相同类型的结果。右操作数应小于 32位,否则只有最低 5 个字节会被使用。

左移 <<

该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充。

例如 3 << 2 的运算图示如下:
3 = 0000 0000 0000 0000 0000 0000 0000 0011
12 = 0000 0000 0000 0000 0000 0000 0000 1100

ps: 对任一数值 x 进行左移n, 相当于十进制里的乘以10的倍数,在这儿是指

x * 2^n

 右移 >>

该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用 0 补充。

例如 8 >> 1 的运算图示如下:
3 = 0000 0000 0000 0000 0000 0000 0000 1000
12 = 0000 0000 0000 0000 0000 0000 0000 0100

ps: 对任一数值 x 进行右移n, 相当于十进制里的除以10的倍数,在这儿是指

x / (2^n)

状态控制

现在有权限1,权限2,权限3; 3种权限;

// 定义三种权限状态分别为1、2、4;
let 权限1 = 1 << 0;  // 1  ->  001
let 权限2 = 1 << 1;  // 2  ->  010
let 权限3 = 1 << 2;  // 4  ->  100

每中角色拥有不同的权限组合;admin拥有所有权限,guest拥有权限2和权限3;

let admin = 权限1 | 权限2 | 权限3; // 7  ->  111
let guest = 权限2 | 权限3;         // 3  ->  011

1. 如何判断角色拥有对应的权限?

// 判断admin是否拥有权限1
if(admin & 权限1 === 权限1){
    console.log("admin拥有权限1")
}
// 判断guest是否没有权限1
if(guest & 权限1 !== 权限1){
    console.log("guest没有权限1")
}
// 判断guest是否拥有权限2、3
if(guest & (权限2 | 权限3) === (权限2 | 权限3)){
    console.log("guest拥有权限2、3")
}

2. 如何为guest赋予权限?

if(guest & 权限1 !== 权限1){
    // 赋予单个权限
    guest |= 权限1;
    // 赋予多个权限
    guest |= (权限1 | 权限n);
}
console.log("guest是否拥有权限1:", guest & 权限1 === 权限1);

3. 如何取消guest的权限?

   3.1:

if(guest & 权限2 === 权限2){
    // 取消单个权限;
    guest &= ~权限2;
    // 取消多个权限;
    guest &= ~(权限2 | 权限n);
}

   3.2:

if(guest & 权限2 === 权限2){
    // 取消单个权限;
    guest ^= 权限2;
    // 取消多个权限;
    guest ^= 权限2 | 权限n;
}

&    判断是否拥有某个状态

|=    添加某个状态

^=    反转(取消)某个状态

Vue3.2关于响应式部分的优化

整理

奇偶数判断:n & 1 === 1;

取整:(~~1.58) == (1.58 | 0)  == 1;

0、1切换:x ^ 1;注:x = 0 | 1;


https://www.kancloud.cn/surahe/front-end-notebook/1616873

https://blog.csdn.net/linxijun120903/article/details/78592313

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值