Hi everyone, I'm Kasong.
In the past two years, many friends and I have React
source code of 06163c4e061d66, such as:
- Why does the scheduler use a small top heap data structure instead of using an array directly?
- Can we use arrays directly in various singly linked lists and circular linked lists in the source code?
- Are various bit operations in the source code necessary?
As a business-dependent framework, in order to improve a little runtime performance, React
never hesitated to write the source code very complicated.
A large number of bit operations are used where states,
flag bits, and
priority operations are involved.
This article will explain the more representative parts. After learning, show your hand when encountering similar scenes, you are the most beautiful boy in the business line.
Several common bit operations
In JS
, the -bit operation will first be converted to
Int32
(32-bit signed integer), after executing -bit operation,
Int32
corresponds to a floating-point number.
In React
, three kinds of bitwise operators are mainly used-bitwise AND, bitwise OR, and bitwise NOT.
Bitwise and (&)
For each of the two binary operands bit
, if both are 1, the result is 1, otherwise it is 0.
For example, to calculate 3 & 2
, first convert the operand to Int32
:
// 3对应的 Int32
0b000 0000 0000 0000 0000 0000 0000 0011
// 2对应的 Int32
0b000 0000 0000 0000 0000 0000 0000 0010
For the sake of intuition, we exclude the first 0 and only keep the last 8 bits (the actual calculation should be 32 bits):
0000 0011
& 0000 0010
-----------
0000 0010
Therefore, the 3 & 2
is converted into a floating-point number to 2.
Bitwise or (|)
For each of the two binary operands bit
, if both are 0, the result is 0, otherwise it is 1.
Calculation 10 | 3
:
0000 1010
| 0000 0011
-----------
0000 1011
The result of the calculation is converted to a floating point number as 11.
Bitwise not (~)
bit
of a binary operand, perform the inversion operation bit by bit (0, 1 interchange)
For ~3
, convert 3 to Int32
then reverse it bit by bit:
// 3对应的 Int32
0b000 0000 0000 0000 0000 0000 0000 0011
// 逐位取反
0b111 1111 1111 1111 1111 1111 1111 1100
The result of the calculation is -4 after being converted into a floating point number.
If you have doubts about this result, you can learn about complement
Let us look at the application of React
Mark status
React
source code, and it is often necessary to determine which context is currently in when executing a function.
Suppose there are three contexts:
// A上下文
const A = 1;
// B上下文
const B = 2;
// 没有处在上下文
const NoContext = 0;
When entering a certain context, you can use bitwise OR operation flag to enter:
// 当前所处上下文
let curContext = 0;
// 进入A上下文
curContext |= A;
We use 8-bit binary as an example (again, it should be Int32 actually, here is for simplification), curContext
and A
perform the OR operation of 16163c4e062196:
0000 0000 // curContext
| 0000 0001 // A
-----------
0000 0001
At this time, you can combine the AND operation of
NoContext
and 06163c4e0621be to determine whether it is in a certain context:
// 是否处在A上下文中 true
(curContext & A) !== NoContext
// 是否处在B上下文中 false
(curContext & B) !== NoContext
After leaving a certain context, combine the bitwise AND and
bitwise non-removal flags:
// 从当前上下文中移除上下文A
curContext &= ~A;
// 是否处在A上下文中 false
(curContext & A) !== NoContext
curContext
and ~A
perform the AND operation of 16163c4e06224d:
0000 0001 // curContext
& 1111 1110 // ~A
-----------
0000 0000
That is, curContext
is removed from A
.
When multiple states need to be processed at the same time in a business, you can use upper-level computing techniques.
Priority calculation
In React
this.setState
under different circumstances will have different priorities. The comparison and selection between priorities also use bit operations.
Specifically, in React
31 bit
bits are used to save update (the reason why it is 31 instead of 32 is because Int32
is the sign bit, and no specific number is stored).
The lower the bit
bit, the higher the update priority (the more it needs priority processing).
For example, suppose there are 2 updates in the current application:
0b000 0000 0000 0000 0000 0000 0001 0001
Among them, the first update priority is the highest (need to be synchronized), and the fifth is the default priority.
React
often necessary to find out which bit the current highest priority update is (the first one in the above example), the method is as follows:
function getHighestPriorityLane(lanes) {
return lanes & -lanes;
}
Explain, because Int32
is complement , so -lanes
can be regarded as the following two-step operation:
- Lanes negated (~lanes)
- plus 1
For intuitiveness, it is represented by 8 bits:
lanes 0001 0001
~lanes 1110 1110 // 第一步
+1 1110 1111 // 第二步
Then lanes & -lanes
as follows:
0001 0001 // lanes
& 1110 1111 // -lanes
-----------
0000 0001
The first one is obtained (the highest priority among existing updates).
Summarize
Although bit operations are not often used in business, it is a convenient and efficient way to perform bit operations in specific scenarios.
Do you love this wave of operations?
Welcome to join the human high-quality front-end framework research group , take flight
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。