JavaScript位运算

341 阅读6分钟

    /**
        @date 2021-11-21
        @description JavaScript位运算
    */

JS中的位运算是对于二进制的运算,使用时会转为整数再转为32位二进制进行计算,然后转回来,有以下7个位运算符:

按位与:&

按位或:|

按位非:~

按位异或:^

左移:<<

右移:>>

无符号右移:>>>

按位与(&)

从一句代码来理解&

const bitAnd = 5 & 7; // 5 

讲解按位与之前我们需要知道与运算是什么,其实就是我们常说的与或非中的,那么就很简单了,先梳理以下的运算结果

valuevalueresult
111
100
010
000

然后再看按位与,就是按每一位做与运算,那么分析题目5 & 7

5 => 00000000000000000000000000000101
7 => 00000000000000000000000000000111
& => 00000000000000000000000000000101 => 5

最后得到的是二进制的101,转回十进制就是5,由此可见按位与是很简单的,只要利用与运算就能得到答案

按位或(|)

同上按位与,按位或也需要理解或运算

valuevalueresult
111
101
011
000

再做5 | 7:

5 => 00000000000000000000000000000101
7 => 00000000000000000000000000000111
| => 00000000000000000000000000000111 => 7

得到111,转回十进制就是7

按位非(~)

同理,先看非运算

valueresult
10
01

但是,再计算~5后,你会发现与预期不一样:

5 => 00000000000000000000000000000101
~ => 11111111111111111111111111111010

能看到得到了一个负数,因为首位是1,不过由于JS采用补码表示负数,那么我们又需要做一些处理才能得到最后的结果,那么问题来了,什么是补码

简单的总结一下原码反码补码

原码:首位表示符号位,其余部分为值,如5的原码是0000000000000000000000000000000000000101,-5的原码是1000000000000000000000000000000000000101

反码:正数的反码就是本身,负数的反码在符号位不变的情况下,其余部分取反,如5的反码就是0000000000000000000000000000000000000101,-5的反码是11111111111111111111111111111010

补码:正数的补码就是本身,负数的补码是在反码的基础上+1,如5的补码是0000000000000000000000000000000000000101,-5的补码是11111111111111111111111111111011

那么也就是说,我们还需要将上面的11111111111111111111111111111010转回原码,再做下一步的处理,补码转原码,就是补码-1再取反码:

11111111111111111111111111111010 => 11111111111111111111111111111001 => 10000000000000000000000000000110 => -6

如果是对负数做按位非,则需要先得到补码,再使用非运算,然后转换就行:

-5 => 10000000000000000000000000000101 => 11111111111111111111111111111010  => 11111111111111111111111111111011
~  => 00000000000000000000000000000100 => 4

其实可以记住对于任何数字x~x = -(x + 1)

按位异或(^)

同上先看异或运算

valuevalueresult
110
101
011
000

再做5 | 7:

5 => 00000000000000000000000000000101
7 => 00000000000000000000000000000111
^ => 00000000000000000000000000000010 => 2

左移(<<)

根据字面意思就能理解,左移就是向左移动x位数

5 << 7

5  => 00000000000000000000000000000101
<< => 00000000000000000000001010000000 => 640

右移(>>)

同理,右移就是向右移动,移出去就是0

5 >> 7

5  => 00000000000000000000000000000101
>> => 00000000000000000000000000000000 => 0

5 >> 2

5  => 00000000000000000000000000000101
>> => 00000000000000000000000000000001 => 1

无符号右移(>>>)

与右移差不多,区别在于首位移动后补0,所以正数与右移是一样的,主要是负数不一样: -5 >>> 2:

-5    => 11111111111111111111111111111011(补码)
>>> 2 => 00111111111111111111111111111110 => 1073741822

无符号右移能保证一定得到正数

日常工作中并不建议使用位运算,这样的代码不太好理解,可能会给别人造成困扰,增加工作难度。

但是基本的了解还是需要的,好好学习,从我做起!