Author: nuysoft/Gao Yun QQ: 47214707 EMail: nuysoft@gmail.com
Statement: This article is an original article. If you need to reprint, please indicate the source and retain the original link.
Before analyzing the Sizzle source code, let’s sort out the working principle of the selector.
First clarify some nouns used in the selector so that there will be no ambiguity when reading later:
Selector Expression: "div > p"
Block expression: "div" "p"
Column selector expression: "div, p"
Block splitter: chunker regular in Sizzle, for selection The expression is divided into block expressions from left to right
Finder: Search for block expressions, and the array of DOM elements found is called the candidate set
Filter: Filter block expressions and candidate sets
The relationship filter filters the relationship between block expressions. There are four relationships in total: " " The immediate sibling relationship; ">" the parent-child relationship; "" the ancestor relationship; and all sibling relationships after "~"
Candidate set: the result of the finder, to be filtered by the filter
Map set: a copy of the candidate set, filter and relational filter to filter the map set
Workflow:
1. Use the block splitter to split the selector expression from left to right
If you encounter a parallel selector expression split by a comma ",", only split it to the selection before the first comma Converter expression 1, record the remaining part
2. Search Sizzle.find for the last block expression, put the result into the candidate set, and delete the matching string part in the block expression
The finder Sizzle.find obtains the corresponding regular expression from the regular set Expr.match and matches the block expression. If the match is successful, it obtains the corresponding search function from the search function set Expr.find and executes it
The search order is defined in In Expr.order, the order is: ID CLASS NAME TAG. When searching for CLASS, the browser needs to support getElementsByClassName
Expr.match sets the regular matching expression of ID CLASS NAME ATTR TAG CHILD POS PSEUDO
3. If the last block expression is not empty (string), the filter Sizzle.filter filters the set
The filter Sizzle.filter only works on a single block expression and only on elements in the candidate set set It works, checking that the elements in the candidate set satisfy the remaining block expressions
During the filtering process of the filter Sizzle.filter, those that do not meet the conditions are set to false, and those that meet the conditions are not modified
when filtering Get the corresponding regular expression from the regular set Expr.leftMatch and match the block expression. If the match is successful, get the corresponding filter function from Expr.filter and execute it
Expr.leftMatch defines the same number of regular expressions as Expr.match Formula: ID CLASS NAME ATTR TAG CHILD POS PSEUDO
Filter function set Expr.filter defines the filter function of PSEUDO CHILD ID TAG CLASS ATTR POS
Filter Sizzle.filter will call the pre-filter Expr before filtering .preFilter corrects the parameters required for filtering, but CLASS is an exception
When CLASS is pre-filtered, it is optimized to directly return elements matching class as a candidate set, narrowing the filtering scope and candidate set scope
Copy the candidate set set obtained by the above search and filtering, and put it into the mapping set checkSet. The subsequent filtering operation is performed on the checkSet
The search and filtering of the last block expression ends here, and a candidate set set and mapping set are obtained. checkSet
4. Filter the remaining block expressions from right to left on the mapping set checkSet, and obtain the corresponding function from the relationship filter set Expr.relative based on the relationship with the previous block expression. Execute relational filtering
During the filtering process of the relational filter Expr.relative, those that do not meet the conditions are set to false, and those that meet the conditions are set to the relationship between the parent element, ancestor element, and brother element
There are four types: " " Immediate brotherhood; ">" father-son relationship; "" ancestor relationship; all brotherhoods after "~"
During the filtering process of the relationship filter Expr.relative, if you encounter If the block expression is the tag TAG, then directly compare the tag type nodeName to see if it is equal
If it is not the tag TAG, the filter Sizzle.filter will be called to filter. See step 3 for the filtering process
From right Filter left until all block expressions are filtered
5. According to the filtered mapping set checkSet, select the final result set from the candidate set set. In the mapping set checkSet
if it is null, false, will be filtered
If it is not Element (nodeType===1), it will be filtered
If the context is not a Document but an Element, not a child element of Element, it will be filtered
6. If there is a parallel expression, repeat 1~5, and merge, sort, and deduplicate the final result set
If there is only one selector expression and no parallel selector expression, no sorting is required
The following process does not belong to Sizzle, but belongs to jQuery's extension of Sizzle
7. If there are multiple contexts, repeat 1~6 for each context
Multiple context examples: $(' div').find('div > p'), $('div') may find multiple divs
In fact, step 7 is the entrance to the jQuery selector. From step 7 to call 1~6, when calling Pass in an empty jQuery object as the result set
By default, document is the context: (context || rootjQuery).find( selector )
8. Merge and remove the result sets found from multiple contexts Repeat, return the result set
done!