By accident, I discovered a new way of doing front-end enumeration. “What is this?” I thought.
After recovering, he exclaimed, “Exquisite! Cattle beep! High efficiency thief!”
I tried to use it in the company’s project, and I really felt that the execution efficiency of the program became faster (of course, there must be a psychological implication).
When Code Review came, my colleagues were shocked:
Let’s see how it works!
Enumeration definition
/** * SKILLS: **/
const SKILLS = {
CSS: 1 ,
JS: 1 << 1.HTML: 1 << 2.WEB_GL: 1 << 3
}
Copy the code
The definition of enumerations seems mundane, but a little strange, right?
Explain:
The << symbol is the bit operator in JS. 1 << N means: move the bits of the number 1 N to the left.
1 << 1 / / 2
// Binary: 1 => 10
1 << 2 / / 4
// Binary: 10 => 100.1 << N // 2 to the N
Copy the code
Second, enumeration use
We defined enumerations as we did in step 1, so how should we use them?
Consider a scenario: When we interview a front end student, we are constantly marking his skills. The marking process is as follows:
let skills = 0
// Add a skill he knows
function addSkill(skill) {
skills = skills | skill / / add
}
addSkill(SKILLS.CSS) / / 1
addSkill(SKILLS.HTML) / / 5
addSkill(SKILLS.WEB_GL) / / 13
Copy the code
Once the skills have been added, we need to spend what skills the person has elsewhere. The spending process is as follows:
// Determine if he knows CSS
SKILLS.CSS & skills // 1 (0 means no, non-0 means yes)
// Determine if he can JS
SKILLS.JS & skills // 0 (0 means no, non-0 means yes)
// Determine if he knows HTML and WebGl
SKILLS.HTML & skills && SKILLS.WEB_GL & skills // 8 (0 means no, non-0 means yes)
// Determine whether he knows JAVASCRIPT or HTML
SKILLS.JS & skills || SKILLS.HTML & skills
Copy the code
OK! The basic skills are there.
Some students are going to ask: “What are its advantages? Such poor readability!”
Of course there are advantages, the advantage lies in: it is efficient thief high!
Three, efficiency comparison
To see how “efficient” it is, I wrote two common “control group” notations.
Common writing method 1: array type play
let skills = []
function addSkill(skill) {
if(! skills.includes(skill)) {// Check whether the skill exists in the spell
skills.push(skill)
}
}
addSkill(SKILLS.CSS) / / 1
addSkill(SKILLS.HTML) / / 5
addSkill(SKILLS.WEB_GL) / / 13
skills.includes(SKILLS.CSS)
skills.includes(SKILLS.JS)
skills.includes(SKILLS.HTML) && skills.includes(SKILLS.WEB_GL)
skills.includes(SKILLS.JS) || skills.includes(SKILLS.HTML)
Copy the code
In this way, an array is used to store the enumeration of skills, and the arr.includes() method is used to determine whether the enumeration has been stored.
Common writing method 2:Map
Type of play
let skills = {}
function addSkill(skill) {
if(! (skills[skill])) {// Check whether the skill exists in the spell
skills[skill] = true
}
}
addSkill(SKILLS.CSS) / / 1
addSkill(SKILLS.HTML) / / 5
addSkill(SKILLS.WEB_GL) / / 13
skills[SKILLS.CSS]
skills[SKILLS.JS]
skills[SKILLS.HTML] && skills[SKILLS.WEB_GL]
skills[SKILLS.JS] || skills[SKILLS.HTML]
Copy the code
The enumeration is stored in {[value]: true} mode and then evaluated in map[value] mode to determine whether the enumeration has been stored.
Comparing the results
Guess what the efficiency ranking would look like? The results are as follows: Fastest group: bitwise group (recommended in this article)
1.1 billion times per second
# 2: Array play
31.24 million executions per second
Slowest group: Map style play
9.52 million times per second
Use case address: jsbench. Me / 4okyr97QI9 /…
Interested friends can visit the link above to verify themselves.
According to the results, there is even a 2-3 data level difference between the fastest and slowest.
Four, principle analysis (why so fast!)
Why is the bitwise formula recommended in this article so efficient? How does it do this through bit operations?
4.1 Definition Principle
This is fromJavascript
The signed integer uses 31 bits to represent the value of the integer, using the first digit32
The symbol for an integer,0
For positive numbers,1
Negative numbers. The value range is[- 2 ^ 31, 2 ^ 31-1)
, namely [-2147483648, 2147483647].When we define enumerations, each occupies a binary value on a different bit.
Therefore, this approach is only suitableFewer than or equal to 31 enumerationsThe scene.
4.2 Principle of value storage
Why skills = skills | skill can be said on this code adds an enumeration item? | is an operator of Javascript: or. When two Numbers for | operation, can compare to each one, any one, if both number is zero, the result is 0. In other cases, the result is 1; Such as:
1 << 1 | 1 << 2 / / 010 | 100
// The result is 110, i.e. the number: 6
1 | 1 << 3 / / 0001 | 1000
// The result is 1001, i.e. the number: 9
Copy the code
Therefore, as long as performed skills = skills | skill, as a result, the skill matching that there must be a 1 a.
4.3 Principle of Value Selection
Why does “SKILLS.CSS & SKILLS” return a non-zero value to indicate that “SKILLS” contains “SKILLS.CSS”? Otherwise, it doesn’t include? & is the Javascript operator: and. When an & is performed on two values, each digit is compared. If both digits are 1, the result is 1. In other cases, the result is 0; Such as:
1 & 9 // 0001 &1001 = 0001 (1)
2 & 8 // 0010&1000 = 0000 (0)
Copy the code
Therefore, if skills. CSS & SKILLS returns a non-zero value, you can determine that skills. CSS must exist in SKILLS.
Five, who is using it? (Rain Creek: I am.)
Where did I see the above usage? Yes, it is from the vue3 source code. Source code address: github1s.com/vuejs/core/…
In the source code, VUe3 defines enumeration in this way, overhead enumeration, it is worth learning. ShapeFlags enumeration is defined as follows:
export const enum ShapeFlags {
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 1 << 1,
STATEFUL_COMPONENT = 1 << 2,
TEXT_CHILDREN = 1 << 3,
ARRAY_CHILDREN = 1 << 4,
SLOTS_CHILDREN = 1 << 5,
TELEPORT = 1 << 6,
SUSPENSE = 1 << 7,
COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
COMPONENT_KEPT_ALIVE = 1 << 9,
COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
}
Copy the code
The end of the
I’m Spring brother. I love vue.js, ElementUI, and Element Plus. My goal is to share the most practical and useful knowledge points with you. I hope you can leave work early, finish your work quickly, and feel calm 🐟.
You can pay attention to me in nuggets: spring elder brother’s dream is to touch fish, can also find me in the public number: the front end to touch fish. I hope you will be stronger in 2022.