今天读书《You Don’t Know JavaScript》,读到强制类型转换一章,其内有提到了JavaScript中的位运算符,正好原来在模拟电路与数字电路课上接触过一些相关的原理,写此文整理一下
经过一番搜罗,基本上是这几个:
- 按位与运算符:
&
- 按位或运算符:
|
- 按位异或运算符:
^
- 按位取反运算符:
~
- 右移运算符:
>>
- 左移运算符:
<<
1. 按位与运算符:&
- 性质:二元运算符
- 用法:
6 & 8 (操作数1 & 操作数2)
- 规则:有 0 则为 0,双 1 则为 1
- 原理:先将6和8转为二进制数,分别为
0000 0110
和0000 1000
// 根据规则:
// 11 -> 1
// 10 00 -> 0
0000 0110
0000 1000
-------------------
0000 0000
得到结果为0000 0000
,转回十进制数就是0
2. 按位或运算符:|
- 性质:二元运算符
- 用法:
1 | 2 (操作数1 | 操作数2)
- 规则:有 1 则为 1,双 0 则为 0
- 原理:先将1和2转为二进制数,分别为
0000 0001
和0000 0010
// 根据规则:
// 10 11 -> 1
// 00 -> 0
0000 0001
0000 0010
-------------------
0000 0011
得到结果为0000 0011
,转换为十进制数后为3
3. 按位异或运算符:^
- 性质:二元运算符
- 用法:
3 ^ 6 (操作数1 ^ 操作数2)
- 规则:10为1,00、11为0(相同位结果为0,不同位结果为1)
- 原理:将 3 和 6 转为二进制数,分别为
0000 0011
和0000 0110
// 根据规则:
// 10 -> 1
// 00 11 -> 0
0000 0011
0000 0110
-------------------
0000 0101
得到结果为0000 0101
,转换为十进制数后为5
4. 按位取反运算符:~
- 性质:一元运算符
- 用法:
~1 (~操作数)
- 规则
- 正数按位取反(见4.1)
- 负数按位取反(见4.2)
4.1 正数按位取反
规则如下:
- 首先将十进制正整数转换为二进制数,这里取
1
为例
1
->0000 0001
- 其次将二进制的原码进行取反,得到结果为
1111 1110
0000 0001
-------------------
1111 1110
- 此时
1111 1110
的第一位1
为符号为,表示这个数的正负,1为负,0为正,这个符号位接下来不参与运算,也就是说我们要取除了第1位的后7位进行运算,此处为:111 1110
,对这个操作数先取反再+1,就是我们最后得到的结果:
// 取反操作
111 1110
-------------------
000 0001
+ 0000 0001 // 十进制的1转成二进制也就是 0000 0001
-------------------
000 0010
- 拼接符号位与运算结果:
1000 0010
第一位符号位为1,表示这是一个负数,计算后面的二进制数得出结果为2,所以结果就是-2
4.2 负数按位取反
规则如下:
- 首先将十进制正整数转换为二进制数,这里取
-2
为例
2
->1000 0010
因为是负数,所以第一位为1 - 保留第1位符号位,对后7位取反且+1
000 0010
-------------------
111 1101
+ 0000 0001
-------------------
111 1110
- 合并符号位与操作数后整体进行取反
1111 1110
-------------------
0000 0001
- 将运算后原码转换为十进制数:
0000 0001
->1
5. 右移运算符:>>
- 性质:二元操作符
- 用法:
3 >> 1 (操作数 >> 右移位数)
- 规则:符号位不变,按位右移,左边补0
- 原理:先把3转换为二进制数
0000 0011
0 |000 0011|
-------|--------|----
0 |000 0001|1 // 最后一位的1因为右移被挤掉了,左边补一个0,因为二进制数的位数是固定的
所以最后得到的结果就是:0000 0001
,转换为十进制数就是1
6. 左移运算符:<<
- 性质:二元操作符
- 用法:
1 << 2 (操作数 << 左移位数)
- 规则:符号位不变,按位左移,右边补0
- 原理:基本的原理与右移运算符一样,先把1转换为二进制数
0000 0001
0 |000 0001|
--------|--------|-
0 00|000 0100| // 左移2位,左边被挤掉2个0,右边补两个0
所以最后得到的结果就是:0000 0100
,转换为十进制数为4
如果这里你跟着写了一遍的话,你会发现:我们可以使用1 << x
来求2的x次幂
,比Math.pow(2, x)
要简洁
小结
虽然平时基本上并不会接触到位级的运算,但该了解的还是要了解到,经常在网上看到JavaScript奇技淫巧用到位运算符,计算机博大精深,路还长,保持向前。