In sizzle, the general idea is to decide whether to support Queryseletorall if it is a composite selector, or call the self-write method Select if not supported.
The Select function is lengthy, and the following analysis Tokenize
The role of the Tokenize function is to parse the selector of a shape like ' ul.topnav > Li,div ' into
[ [{value:' ul ', type: ' TAG ', matches:[' ul ']},{value: '. Topnav ', type: ' CLASS ', matches:[' Topnav ']},{ Value: ' > ', type: ' > '},{value: ' Li ', type: ' tag ', matches:[' Li '}], [{value:' div ', type: ' Tag ', matches:[' div ']} ]
Each comma resolves to an array that represents an independent selector item, and the selection relationship of each independent selector item is parsed into the above format according to Class,tag,id and relationships.
This type of parsing is a fixed format for finding elements below, first without considering the following, we first analyze the implementation of tokenize.
//Cache function Creation functionvarCreatecache =function(){ //cache function Common array varKeys = []; return functionCache (name,value) {//when the length is greater than a constant, clear the old element and insert the new element if(Keys.push (name) > 1){ Deletecache[Keys.shift ()]}; returnCache[name] =value; };}//Caching Function Objects//This is a method by which the cached data can be stored in this function (also the object). varTokencache =Createcache ();//Simple Regular Filter ObjectvarFilter ={TAG:/^ (\w+)/, ID:/^# (\w+)/, CLASS:/^\. (\w+)/}//Relationship Matching RegularvarRelation =/^\s* ([\>\+\~]|^\s) \s*/;//Comma regularvarComma =/^\,/;functiontokenize (selector) {varcached =Tokencache[selector]; //The cache has results and returns directly if(cached) {returncached; } //Cycle Conditions varSofar =Selector,//result ArrayGroups = [], //Matching Parametersmatched,//a standalone selector itemtoken = [], //auxiliary parameter regular match resultmatch; //Loop Resolution Selector while(sofar) {//Create a separate selector item for the first time by default //then create by judging the comma if(!matched | | (match =comma.exec (SOFAR))) { if(match) {//to save unresolved selectorsSofar = Sofar.slice (match[0].length); } groups.push (Token= []); } //each time the loop sets the secondary match parameter to false, if there is no match then there is no bounce through breakmatched =false; //matching relationships > etc. //Parse Save Results if(match =relation.exec (SOFAR)) {Matched=Match.shift (); Token.push ({value:matched, type:match[0].replace (/\s+/g, "")}) Sofar=Sofar.slice (matched.length)}//Match selector Class,tag,id //Parse Save Results for(varTypeinchfilter) { if(match =filter[type].exec (SOFAR)) {Matched=Match.shift (); Token.push ({value:matched, Type:type, Matches:match }) Sofar=Sofar.slice (matched.length)}} //did not jump out of the loop. if( !matched) { Break; } } //caches the results and returns return(Tokencache (selector,groups));} Console.log (Tokenize (' Ul.topnav > Li,div ')) Console.log (Tokenize (' A Li '))
This is my analog input and output of the function written out, jquery source code in the implementation of the main function based on a lot of compatibility processing.
Caching is very common in jquery, and here again the basic idea is to store the function input value key, and the output value in the cache object, until the next time the function is called, if there is a value in the cache object, it is read directly.
The cache for this example is slightly more complex, and it uses functions to store cached data in objects of the same name. Also, the author wants several cache-sharing lengths, where the function to create the cache function is used.
The tokenize of Sizzle