Select function
The function of the Tokensize function has been introduced, and a tokens array has been generated, and we have introduced the composition of it, and the following is how to deal with this tokens array.
The connection relationship between DOM elements is about > + ~ Several, including spaces, while the tokens array is a type that has tags, attr, and connectors, distinguishing them Sizzle is a set of rules, such as the one we talked about in the previous chapter about the Expr object, which is really important:
expr.relative = {
">": {dir: "ParentNode", First:true}, "
" ": {dir:" ParentNode "},
" + ": {dir:" Previou Ssibling ", first:true},
" ~ ": {dir:" PreviousSibling "}
};
The expr.relative tag is used to differentiate the connectors and classify them by category.
Now, let's get this over with. Tokens array, this array is currently a multi-array, and now does not consider the comma case, tentatively only one branch. If we use right-to-left matching, div > div.seq h2 ~ P, will first get the type TAG token, and for the type of token we can already use relative object to judge, now to introduce EXPR.F IND object:
Expr.find = {};
expr.find[' id ' = function (ID, context) {
if (typeof Context.getelementbyid!== "undefined" && Documentisht ML) {
var elem = Context.getelementbyid (ID);
return elem? [Elem]: [];
}
;
expr.find["CLASS"] = support.getelementsbyclassname && function (className, context) {
if (typeof context.g Etelementsbyclassname!== "undefined" && documentishtml) {
return context.getelementsbyclassname ( className);
}
};
expr.find["TAG"] = function () {...};
In fact, the source of JQuery is also considered compatibility, here with find["ID" introduced:
if (Support.getbyid) {
expr.find[' id '] = function () {...};//above
}else{
//compatible with IE 6, 7
expr.find["id"] = function (ID, context) {
if (typeof Context.getelementbyid!== "undefined" && documentishtml) {
var nod E, I, Elems,
elem = Context.getelementbyid (ID);
if (elem) {
//Verify the id attribute
node = elem.getattributenode ("id");
if (node && node.value = = = id) {
return [elem];
}
Fall back on getelementsbyname
Elems = context.getelementsbyname (ID);
i = 0;
while ((Elem = elems[i++]) {
node = Elem.getattributenode ("id");
if (node && node.value = = = id) {
return [elem];}}
}
return [];
}
};
}
You can simplify the Find object:
Expr.find = {
"ID": document.getElementById,
"CLASS": Document.getelementsbyclassname,
"TAG": document.getElementsByTagName
}
Expr.filter will also be introduced later. Select Source
Before the source code, look at a few regular expressions.
var runescape =/\\ ([\da-f]{1,6}[\x20\t\r\n\f]?| ([\x20\t\r\n\f]) |.) /gi
//This regular is used for the escape character special processing, with a backslash token
runescape.exec (' \\ab ');//["\ab", "AB", undefined]
var rsibling =/[+ ~]/; Match +, ~
matchexpr[' needscontext '] =/^[\x20\t\r\n\f]*[>+~]|:( Even|odd|eq|gt|lt|nth|first|last) (?: \ ([\x20\t\r\n\f]* (?:-\ d)? \d*) [\x20\t\r\n\f]*\] |) (? =[^-]|$)/
i//needscontext used to match an incomplete selector
matchexpr[' needscontext '].test (' + P ')//true
matchexpr [' Needscontext '].test (': First-child P ')//true
//This incomplete, may be due to the redeployment of #ID caused by
For RuneScape, it is often used with replace:
var str = ' \\ab ';
Str.replace (RuneScape, funescape);
var Funescape = function (_, escaped, Escapedwhitespace) {
var = "0x" + escaped-0x10000;
NaN means Non-codepoint
//support:firefox<24
//Workaround erroneous numeric interpretation of + "0x"
Return high!== High | | Escapedwhitespace? Escaped:high < 0?
BMP codepoint
String.fromCharCode (High + 0x10000):
//Supplemental Plane codepoint (surrogate pair)
String.fromCharCode (High >> Ten | 0xD800, High & 0X3FF | 0xdc00);
}
I completely do not understand, you have the sense to go, O (∩_∩) o haha ~
var select = Sizzle.select = function (selector, context, results, seed) {var I, tokens, token, type, find, compiled = typeof selector = = = "function" && selector, match =!seed && tokenize ((selector = Compiled.selector | |
selector)); Results = Results | |
[];
The length is 1, which means that there is no comma, Sizzle attempts to optimize this condition if (match.length = = = 1) {tokens = match[0] = match[0].slice (0); The first TAG is an ID selector, which sets the Quick find if (Tokens.length > 2 && (token = tokens[0]). Type = = = "ID" && context. NodeType = = = 9 && documentishtml && Expr.relative[tokens[1].type]) {//Set new context to that ID con Text = (expr.find["ID"] (Token.matches[0].replace (RuneScape, Funescape), context) | |
[]) [0];
if (!context) {///The first ID is not found, it returns the return results directly;
At this point selector is a function, there should be a special purpose} else if (compiled) {context = Context.parentnode;
} selector = Selector.slice (Tokens.shift (). Value.length); }//InNo child case, right-to-left, is still optimized for performance i = matchexpr["Needscontext"].test (selector)?
0:tokens.length;
while (i--) {token = tokens[i];
Encounter +~ and other symbols first stop if (expr.relative[(type = Token.type)]) {break; } if (find = Expr.find[type]) {//Search, expanding context for leading sibling combinators if (( Seed = Find (Token.matches[0].replace (RuneScape, Funescape), Rsibling.test (Tokens[0].type) && TestContext ( Context.parentnode) | | Context)) {//TestContext is to determine if getelementsbytagname exists//If seed is empty or no tokens remain, we
Can return early tokens.splice (I, 1);
selector = seed.length && toselector (tokens);
Selector is empty, indicating the head, directly returning if (!selector) {push.apply (results, seed);
return results;
} break; }}}}//Compile and execute a filtering function if one is not provided//ProvidE ' match ' to avoid retokenization if we modified the selector above (compiled | | compile (selector, match)) (SEED, cont Ext,!documentishtml, results,!context | | Rsibling.test (selector) && testContext (context.parentnode) | |
context);
return results; }
The Toselector function is to remove the tokens that has been selected to stitch the rest into a string:
function Toselector (tokens) {
var i = 0,
len = tokens.length,
selector = "";
for (; i < Len; i++) {
selector + = Tokens[i].value;
}
return selector;
}
In the end, there is a compile function, which is the compiler function of Sizzle, and the following chapter says.
So far, the optimizations have been optimized, selector and context, as well as seed, and if executed to the compile function, the state of these variables: selector may not have been the first one, through various head-to-tail; match has not changed, still The result of the tokensize, the Seed collection, all the collections waiting to match the DOM, the context may already be the head (#ID); The results is not changed.
As you can see, in fact compile is an asynchronous function compile (). Summary
Select probably did a few things, assigning the result of tokenize processing selector to match, so match is a tokens array, and in the case of length 1 and the first token as ID, the context is optimized, the ID The matched element is assigned to the context, and if it does not contain a needscontext regular, a seed collection is generated for all the right-most DOM collections; the last thing compile function, the parameters are really many ... Reference
JQuery 2.0.3 Source Analysis sizzle engine-analytic principle