二进制在react源码中的应用
点击 这里 查看源码
...
// DOM需要插入到页面中
export const Placement = /* */ 0b00000000000010;
// DOM需要更新
export const Update = /* */ 0b00000000000100;
// DOM需要插入到页面中并更新
export const PlacementAndUpdate = /* */ 0b00000000000110;
// DOM需要删除
export const Deletion = /* */ 0b00000000001000;
...
以上是关于react源码中的节选,但我并不想展开讲源码的内容,只是想让大家知道二进制在实际开发中的使用。
js中的二进制
// js中的二进制是以0b开头的,如下所示:
// 正数
console.log(0b00000000000010); // 2
console.log(0b00000000000100); // 4
// 负数
console.log(-0b00000000000010); // -2
console.log(-0b00000000000100); // -4
原码、反码、补码
- 原码:二进制表示法,最高位表示符号位,0表示正数,1表示负数
- 反码:正数的反码与原码相同,负数的反码是对原码逐位取反,符号位保持不变
- 补码:正数的补码与原码相同,负数的补码是对原码逐位取反,然后在最后一位加1
下面是几个例子:
/*
例:求5的二进制原码、反码、补码(三个都相同)
5的二进制原码:00000000000000000000000000000101
5的反码:00000000000000000000000000000101
5的补码(反码+1):00000000000000000000000000000101
例:求-5的二进制原码、反码、补码
-5的二进制原码:-101
-5的反码:11111111111111111111111111111010
-5的补码(反码+1):11111111111111111111111111111011
*/
位运算符
位运算符主要分为两大类
1、位移运算符:
- <<:左移,将一个数的二进制码整体左移若干位,高位丢弃,低位补0
- >>:右移,将一个数的二进制码整体右移若干位,对正数,高位补0,对负数,高位补1
- >>>:无符号右移,将一个数的二进制码整体右移若干位,高位补0
注意:位移运算符是对数的补码进行位移
下面是几个列子:
/*
例:
正数:
5的补码为00000000000000000000000000000101
5 << 2:00000000000000000000000000010100,结果为20
5 >> 2:00000000000000000000000000000001,结果为1
负数:
这里的-5要先求出补码,-5的补码为11111111111111111111111111111011
-5 << 2:11111111111111111111111111101100,结果为-20
-5 >> 2:11111111111111111111111111111110,结果为-2
-5 >>> 2:00111111111111111111111111111110,结果为1073741822
说明:
-5 << 2 => 11111111111111111111111111101100
这里算出的是补码,所以要转换成原码
已知负数的补码是对其反码+1,所以其反码为
11111111111111111111111111101100 - 1 = 11111111111111111111111111101011
所以其原码为
10000000000000000000000000010100 => -20
*/
2、位逻辑运算符
- &:按位与,两个数的二进制码对应位都为1,结果为1,否则为0
- |:按位或,两个数的二进制码对应位都为0,结果为0,否则为1
- ^:按位异或,两个数的二进制码对应位相同,结果为0,否则为1
- ~:按位非,对一个数的二进制码按位取反,即0变1,1变0
下面是几个列子:
const C = 0b101;
const D = 0b110;
// C & D => 0b100
// C | D => 0b111
// C ^ D => 0b011
/*
例:
~5
5的补码为00000000000000000000000000000101
~5 => 11111111111111111111111111111010
5的反码为11111111111111111111111111111001
5的原码为10000000000000000000000000000110
所以~5的结果为-6
~-5
-5的补码为11111111111111111111111111111011
~-5 => 00000000000000000000000000000100
-5的反码为11111111111111111111111111111011
-5的原码为10000000000000000000000000000100
所以~5的结果为4
*/
注意:~是对数的补码进行取反
二进制在权限控制中的应用
回归主题,我们声明几个变量,分别表示权限:
const read = 0b100; // 读的权限
const write = 0b010; // 写的权限
const execute = 0b001; // 执行的权限
// 添加权限
// 我们我们想给某个用户添加读写和执行权限,那么我们可以这样做
const readAndWrite = read | write | execute; // 0b111
// 检查权限
// 我们想检查某个用户是否有某种权限,那么我们可以这样做
const hasRead = (readAndWrite & read) === read; // true
const hasWrite = (readAndWrite & write) === write; // true
// 删除权限
// 我们想删除某个用户的某种权限,那么我们可以这样做:给想要删除的权限取反,然后与原权限进行按位与运算
const noRead = readAndWrite & ~read; // 0b011
const noWrite = readAndWrite & ~write; // 0b101
const noExecute = readAndWrite & ~execute; // 0b110
拓展,小数的二进制表示
/*
例如:0.6
方法:乘2取整,直到小数为0
0.6 * 2 = 1.2 => 1
0.2 * 2 = 0.4 => 0
0.4 * 2 = 0.8 => 0
0.8 * 2 = 1.6 => 1
0.6 * 2 = 1.2 => 1
0.2 * 2 = 0.4 => 0
0.4 * 2 = 0.8 => 0
0.8 * 2 = 1.6 => 1
...
此时,0.6是一个无限循环小数,二进制码为:0b0.1001100110011001100110011001100110011001100110011001...
Q:为什么 0.1 + 0.2 = 0.30000000000000004
0.1的二进制码:0b0.0001100110011001100110011001100110011001100110011001...
0.2的二进制码:0b0.0011001100110011001100110011001100110011001100110011...
0.1 + 0.2的二进制码:0b0.0100110011001100110011001100110011001100110011001100...
0.1 + 0.2的十进制码:0.30000000000000004
*/