位运算
位运算就是基于整数的二进制表示进行的运算。由于计算机内部就是以二进制来存储数据,位运算是相当快的,但不直观且只支持整数运算。
合理的运用位运算更能显著提高代码在机器上的执行效率。
特性
位运算 | 用法 | 描述 |
---|---|---|
与(& ) |
a & b |
两个对应位都为 1 时,结果为 1,否则为 0 |
或(\| ) |
a \| b |
两个对应位都为 0 时,结果为 0,否则为 1 |
异或(^ ) |
a ^ b |
两个对应位相同时,结果为 0,否则为 1 |
非/取反(~ ) |
~ a |
反转操作数, 即 0 变成 1, 1 变成 0 |
左移(<< ) |
a << b |
将 a 的二进制形式向左移 b (< 32) 位,右边用 0 填充 |
右移(>> ) |
a >>> b |
将 a 的二进制形式向右移 b (< 32) 比特位,左侧补 0 |
JS 中位运算中的左右操作数都转换为有符号32位整型
, 且返回结果也是有符号32位整型
- 当操作数是浮点型时首先会被转换成整型(丢弃小数位),再进行位运算
- 当操作数过大,超过了
Int32
范围,超过的部分会被截取
基本使用
基本使用
枚举属性:
通过位移的方式, 定义一些枚举常量
const A = 1 << 0; // 0b00000001
const B = 1 << 1; // 0b00000010
const C = 1 << 2; // 0b00000100
位掩码:
通过位移定义的一组枚举常量, 可以利用位掩码的特性, 快速操作这些枚举产量(增加, 删除, 比较).
- 属性增加
|
ABC = A | B | C
- 属性删除
& ~
AB = ABC & ~C
- 属性比较
- AB 当中包含 B:
AB & B === B
- AB 当中不包含 C:
AB & C === 0
- A 和 B 相等:
A === B
- AB 当中包含 B:
const A = 1 << 0; // 0b00000001
const B = 1 << 1; // 0b00000010
const C = 1 << 2; // 0b00000100
// 增加属性
const ABC = A | B | C; // 0b00000111
// 删除属性
const AB = ABC & ~C; // 0b00000011
// 属性比较
// 1. AB当中包含B
console.log((AB & B) === B); // true
// 2. AB当中不包含C
console.log((AB & C) === 0); // true
// 3. A和B相等
console.log(A === B); // false
React 中的使用场景
优先级管理 lanes
lanes 是17.x
版本中开始引入的重要概念,代替了16.x
版本中的expirationTime
,作为fiber
对象的一个属性(位react-reconciler
包),主要控制 fiber 树在构造过程中的优先级。
变量定义:
源码ReactFiberLane.js中的定义
export type Lanes = number;
export type Lane = number;
export const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000;
export const NoLane: Lane = /* */ 0b0000000000000000000000000000000;
export const SyncLane: Lane = /* */ 0b0000000000000000000000000000001;
export const SyncBatchedLane: Lane = /* */ 0b0000000000000000000000000000010;
export const InputDiscreteHydrationLane: Lane = /* */ 0b0000000000000000000000000000100;
const InputDiscreteLanes: Lanes = /* */ 0b0000000000000000000000000011000;
const InputContinuousHydrationLane: Lane = /* */ 0b0000000000000000000000000100000;
const InputContinuousLanes: Lanes = /* */ 0b0000000000000000000000011000000;
// ...
一些方法定义:
getHighestPriorityLanes
: 获取最高优先级
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
// 判断 lanes中是否包含 SyncLane
if ((SyncLane & lanes) !== NoLanes) {
return_highestLanePriority = SyncLanePriority;
return SyncLane;
}
// 判断 lanes中是否包含 SyncBatchedLane
if ((SyncBatchedLane & lanes) !== NoLanes) {
return_highestLanePriority = SyncBatchedLanePriority;
return SyncBatchedLane;
}
// ...
// ... 省略其他代码
return lanes;
}
getHighestPriorityLane
: 分离出最高优先级
function getHighestPriorityLane(lanes: Lanes) {
return lanes & -lanes;
}
getLowestPriorityLane
: 分离出最低优先级
function getLowestPriorityLane(lanes: Lanes): Lane {
// This finds the most significant non-zero bit.
const index = 31 - clz32(lanes);
return index < 0 ? NoLanes : 1 << index;
}
总结
React 中有大量的位运算的应用,比如 ReactFiberLane.js
中的优先级管理,除此之外还有 ExecutionContext
、effectTags
的使用。使用位运算不仅是提高运算速度,且位掩码能简洁和清晰的表示出二进制变量之间的关系。