Author: nuysoft/high cloud QQ: 47214707 Email: nuysoft@gmail.com
Disclaimer: This article is an original article. If you need to reprint it, please indicate the source and retain the original article link.
Jquery source code analysis series (Continuous updates)
In the design philosophy of sizzle, the general design ideas of the CSS selector engine are decomposed and deduced. In the working principle of sizzle, the creative right-to-left algorithm of sizzle is implemented, A detailed analysis is made.
However, from right to left does not apply to all selector expressions. This article will analyze the necessity and application scenarios of left to right, and the reasons why the efficiency is higher from right to left.
Let's take a look at the classic example below:
$ ('Div button: first ') |
: First is the position filter. The first of all buttons Under the DIV matches only one element. |
$ ('Div button: First-child ') |
: First-child is a child element filter. The first one in the button under each Div matches a child element button for each parent element Div, the button must be the first child element of the DIV to match) |
For $ ('div button: First ') containing the position filter, let's try what will happen from right to left:
1. Select Search button: first, find all the buttons Based on the tag, and then use the set filter expr. setfilters. First to find the first button.
2. Step 2? No Step 2! Step 1st is incorrect. The first step is to find the first button of all buttons, and we are looking for the first button in the div.
Let's analyze the differences between first and first-child filter objects:
: The first filter object is the search/filter result of the 'div click', depending on the previous block expression.
: The filter object of first-child is 'click' itself. How can this problem be solved? To check whether the 'button 'is the first element under its parent element, you can use the 'button' to perform this filter, because the 'button 'can be used to locate the parent element, then, check whether the filtered 'button 'ancestor is Div.
The concept of "dependency" mentioned here is somewhat vague, because as long as there are multiple block expressions, the latter must always be dependent on the front. Naturally, the child element, child element, and sibling element of the front side.
The "dependency" mentioned here refers to not the natural relationship between block expressions, but the filtering of a single block expression cannot be performed independently. It must be determined after the search/filter result of the previous block expression, to filter the current block expression.
$ ('Div button: first') workflow should be from left to right:
1. Find the DIV
2. Find all buttons Under all Div
3. Find the first of all buttons.
It can be seen that from right to left is not omnipotent. If necessary, we still need to change from left to right. When do we need to change from left to right?
The answer is when there is a location filter.
Because the filtering result of the block expression where the location filter is located depends on the result of finding/filtering the block expression before it, all must first find/filter the previous one, that is, from left to right; other filters only depend on the current element. Let's see how the source code of sizzle judges from left to right or from right to left:
// Matches multiple block selectors and is a location filter (pseudo class)/:( nth | EQ | GT | lt | first | last | even | ODD )(? : \ (\ D *)\))? (? = [^ \-] | $ )/ If (parts. length> 1 & origpos.exe C (selector )){ // Left to right // Some code... } Else { // Right to left // Some code... } |
The workflow from left to right is organized as follows:
1. Use the splitter to split the selector expression from left to right.
----- The following is from left to right -----
2. The 1st block expressions are displayed in the header of the split result array. Call the sizzle function to perform a complete search and filter to obtain the context array set,
Same as step 2 and 3 of "from right to left"
3. the first block expression is displayed from the header of the split result array. The position selector posprocess is called, set is the context, and the returned result is used as the context of the next block expression.
If you encounter a relationship between blocks, take another block expression.
The following is the execution process of the position selector posprocess:
Position selector posprocess extracts all the pseudo classes in the block expression, stores them to the pseudo-class variable later, and deletes the pseudo classes matched in the block expression.
Take every element in the set as the context. Call the sizzle function to perform a complete search and filter for the block expression that removes the pseudo class, and aggregate the results and store them in the tmpset
Call the filter sizzle. Filter to filter the result set tmpset and use the pseudo class as the filter expression.
Done. Execution of a block expression is complete!
4. Repeat Step 1 and execute Step 1 from left to right for the remaining block expression. The final result is used as the candidate set and ing set checkset.
Each block expression executes a position selector posprocess. Each parsing result set serves as the context of the next block expression, narrowing the context continuously (the core idea of left-to-right is to keep narrowing the context)
This is why the efficiency is higher from right to left:
From the right to the left, only the last block expression is completely searched and filtered, and all other block expressions are filtered.
However, from left to right, you need to parse each element in the result of the previous block expression as the context, and perform a complete search and filter on the current block expression.
----- Complete from left to right -----
5. Based on the filtered ing set checkset, select the final result set from the candidate set, and in the checking set checkset
6. If a parallel expression exists, repeat 1 ~ 5. Combine, sort, and deduplicate the final result sets to return the final result set.
7. If multiple contexts exist, repeat 1 ~ for each context ~ 6
8. returns the result set from multiple contexts and deduplication.
1st, 5, 6, 7, and 8 are exactly the same as from right to left. For detailed analysis, refer to the working principle of sizzle. You can set the process from left to right and from right to left, put it together for a comparative study.
If you are interested, you can take these processes and analyses and compare them with the source code of sizzle. You can understand the ideas and skills only after you have actually read them.