Hello, everyone. I am Karsong.
React source code:
-
Why does the scheduler use a small top heap instead of an array?
-
Source in a variety of one-way linked list, circular linked list, directly with array?
-
All kinds of bit operations in the source code, is it necessary?
As a business-dependent framework, React doesn’t shy away from writing complex source code for a bit of runtime performance.
Bitwise operations are used extensively where state, flag bit, and priority operations are involved.
This article will explain some representative parts of them. Once you’ve learned that, when you’re in a situation like this, you’ll be the best guy in your line of business.
Several common bit operations
In JS, the bit operand is first converted to Int32 (a 32-bit signed integer), and then Int32 corresponds to a floating point number.
React uses three bitwise operators — bitwise and, bitwise or, bitwise not.
Bitwise and (&)
For each bit of the two binary operands, the result is 1 if both are 1, and 0 otherwise.
For example, to compute 3&2, first convert the operand to Int32:
// 3 corresponds to Int32
0b000 0000 0000 0000 0000 0000 0000 0011
// 2 corresponds to Int32
0b000 0000 0000 0000 0000 0000 0000 0010
Copy the code
For the sake of intuition, we exclude the preceding 0 and keep only the last 8 bits (actually 32 bits are involved in the calculation) :
0000 0011
& 0000 0010
-----------
0000 0010
Copy the code
So the 3&2 result is 2 when converted to a floating point number.
Bitwise or (|)
For each bit of the two binary operands, the result is 0 if both are 0, and 1 otherwise.
Computation 10 | 3:
0000 1010
| 0000 0011
-----------
0000 1011
Copy the code
When converted to a floating point number, the result is 11.
Bitwise non (~)
Bit by bit on each bit of a binary operand (0, 1 interchanged)
For ~ 3, convert 3 to Int32 and negate bit by bit:
// 3 corresponds to Int32
0b000 0000 0000 0000 0000 0000 0000 0011
// reverse bit by bit
0b111 1111 1111 1111 1111 1111 1111 1100
Copy the code
The result is -4 when converted to a floating point number.
If you are confused about this result, you can learn about complement
Let’s look at bitwise operations in React from easy to hard.
Flag state
The React source code has multiple contexts, and you often need to determine which context you are in when executing a function.
Suppose there are three context cases:
// A context
const A = 1;
// B context
const B = 2;
// Not in context
const NoContext = 0;
Copy the code
When entering a context, you can use bitwise or action flags to enter:
// The current context
let curContext = 0;
// Enter A context
curContext |= A;
Copy the code
Using an 8-bit binary example (again, really Int32, for simplicity), curContext and A perform bit-or operations:
0000 0000 // curContext
| 0000 0001 // A
-----------
0000 0001
Copy the code
We can use bitwise and operations with NoContext to determine whether we are in a particular context:
// Is in the context of A true(curContext & A) ! == NoContext// is in the context of B false(curContext & B) ! == NoContextCopy the code
After leaving a context, combine bitwise and bitwise non-remove flags:
// Remove context A from the current context
curContext &= ~A;
// is in the context of A false(curContext & A) ! == NoContextCopy the code
CurContext and ~A perform bitwise and operations:
0000 0001 // curContext
& 1111 1110 // ~A
-----------
0000 0000
Copy the code
Remove A from curContext.
When you need to process multiple states at the same time in your business, you can use the bitwise manipulation technique above.
Priority calculation
In React, updates triggered by this.setState will have different priorities depending on the situation. The comparison and selection of priorities also use bit operations.
Specifically, React stores updates with 31 bits (31 instead of 32 because Int32’s highest bit is a sign bit and does not store specific numbers).
The lower the bit, the higher the update priority.
For example, suppose there are two updates to the current application:
0b000 0000 0000 0000 0000 0000 0001 0001
Copy the code
The first bit has the highest update priority (synchronization is required), and the fifth bit has the default priority.
React often needs to find out which update has the highest priority (in the example above), as follows:
function getHighestPriorityLane(lanes) {
return lanes & -lanes;
}
Copy the code
Int32 uses complement code, so -lanes can be regarded as the following two steps:
-
(~lanes)
-
Add 1
For intuition, use 8 bits:
lanes 0001 0001
~lanes 1110 1110 / / the first step
+1 1110 1111 / / the second step
Copy the code
Lanes & -lanes:
0001 0001 // lanes
& 1110 1111 // -lanes
-----------
0000 0001
Copy the code
The first digit is taken (the highest priority of any existing update).
conclusion
Although bitwise operation is not often used in business, it is a convenient and efficient way to perform bitwise operation in certain scenarios.
Did you love this wave operation?
Welcome to join the Human high quality front-end framework research group, Band fly