位运算符基本使用 按位与(&):a & b对于每一个比特位,两个操作数都为 1 时, 结果为 1, 否则为 0按位或(|):a | b对于每一个比特位,两个操作数都为
位运算符基本使用
0000 0000 0000 0000 0000 0000 0000 0011 -> 3
1111 1111 1111 1111 1111 1111 1111 1100 -> ~ 3 = -4
左移位<<:各二进位全部左移若干位,高位丢弃,低位补0。
0000 0000 0000 0000 0000 0000 0000 0110 -> 6
0000 0000 0000 0000 0000 0000 0001 1000 -> 6 << 2 = 24
右移位>>:各二进位全部右移若干位,正数高位补0,负数高位补1,低位丢弃
0000 0000 0000 0000 0000 0000 0000 1100 -> 12
0000 0000 0000 0000 0000 0000 0000 0011 -> 12 >> 2 = 3
负数情况:
1111 1111 1111 1111 1111 1111 1111 0100 -> -12
1111 1111 1111 1111 1111 1111 1111 1101 -> -12 >> 2 = -3
无符号右移位>>>:各二进位全部右移若干位,高位补0,低位丢弃。
0000 0000 0000 0000 0000 0000 0000 1100 -> 12
0000 0000 0000 0000 0000 0000 0000 0011 -> 12 >>> 2 = 3
1111 1111 1111 1111 1111 1111 1111 0100 -> -12
0011 1111 1111 1111 1111 1111 1111 1101 -> -12 >> 2 = 1073741821
正数计算负数:
取反后+1
+5:0101
-5:取反1010 最低位+1 = 1011,1011即为二进制的-5
负数倒推正数:同样为取反后+1
在js中位运算的特点
'str' >>> 0; // ===> Number('str') >>> 0 ===> NaN >>> 0 = 0
位掩码
通过位移定义的一组枚举常量, 可以利用位掩码的特性, 快速操作这些枚举产量(增加, 删除, 比较)
const A = 1 << 0; // 0b00000001
const B = 1 << 1; // 0b00000010
const C = 1 << 2; // 0b00000100
属性增加|
ABC = A | B | C //0b00000111
属性删除& ~
AB = ABC & ~C //0b00000011
属性比较
AB 当中包含 B: AB & B === B。// AB & B =>0b00000010 ===B,true
AB 当中不包含 C: AB & C === 0 // AB & C =>0b00000000 === 0,true
react中的位运算
标记状态
// A上下文
const A = 1; //0001
// B上下文
const B = 2; //0010
// 当前所处上下文
let curContext = 0;
// 没有处在上下文的标志
const NoContext = 0;
假设进入A的上下文
curContext |= A; //即curContext=curContext|A =>0001
判断是否处在某一上下文中,结合按位与操作与NoContext
// 是否处在A上下文中,这里为true
(curContext & A) !== NoContext //curContext & A)=>0001 !==0000,所以为true,表示在A的上下文中
// 是否处在B上下文中,这里为false,和上方同理
(curContext & B) !== NoContext
离开上下文,取出标记进行恢复
// 从当前上下文中移除上下文A
curContext &= ~A; //curContext=curContext& ~A,即0001&1110=0000,进行恢复
// 是否处在A上下文中,此处为false
(curContext & A) !== NoContext //(curContext & A)为0000
ReactFiberLane.js
//类型定义
export opaque type Lanes = number;
export opaque 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;
// ...
// ...
const NonIdleLanes = 0b0000111111111111111111111111111;
export const IdleHydrationLane: Lane = 0b0001000000000000000000000000000;
const IdleLanes: Lanes = 0b0110000000000000000000000000000;
export const OffscreenLane: Lane = 0b1000000000000000000000000000000;
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
0b000 0000 0000 0000 0000 0000 0001 0001
function getHighestPriorityLane(lanes) {
return lanes & -lanes;
}
-lanse:
lanes 0001 0001
~lanes 1110 1110 // 第一步
+1 1110 1111 // 第二步
0001 0001 // lanes
& 1110 1111 // -lanes
-----------
0000 0001
若lanes为0001 0000
0001 0000 // lanes
& 1111 0000 // -lanes
-----------
0001 0000
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-reconciler上下文定义
export const NoContext = 0b0000000;
const BatchedContext = 0b0000001;
const EventContext = 0b0000010;
const DiscreteEventContext = 0b0000100;
const LegacyUnbatchedContext = 0b0001000;
const RenderContext = 0b0010000;
const CommitContext = 0b0100000;
export const RetryAfterError = 0b1000000;
// ...
// Describes where we are in the React execution stack
let executionContext: ExecutionContext = NoContext;
scheduleUpdateOnFiber
// scheduleUpdateOnFiber函数中包含了好多关于executionContext的判断(都是使用位运算)
export function scheduleUpdateOnFiber(
fiber: Fiber,
lane: Lane,
eventTime: number,
) {
if (root === workInProgressRoot) {
// 判断: executionContext 不包含 RenderContext
if (
deferRenderPhaseUpdateToNextBatch ||
(executionContext & RenderContext) === NoContext
) {
// ...
}
}
if (lane === SyncLane) {
if (
// 判断: executionContext 包含 LegacyUnbatchedContext
(executionContext & LegacyUnbatchedContext) !== NoContext &&
// 判断: executionContext 不包含 RenderContext或CommitContext
(executionContext & (RenderContext | CommitContext)) === NoContext
) {
// ...
}
}
// ...
}
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!
--结束END--
本文标题: react 源码中位运算符的使用详解
本文链接: https://lsjlt.com/news/141624.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0