0 Comments

Sizzle构造器

发布于:2013-06-01  |   作者:广州网站建设  |   已聚集:人围观
Sizzle构造器

在jquery.fn.init()构造器函数中,通过调用jQuery(context).find(selector)函数来解析并匹配DOM元素。jQuery.find()函数实际上是引用Sizzle()函数,而Sizzle()函数仅是Sizzle引擎的构造器,它主要调用Sizzle.find()函数在DOM文档树中查找与CSS语法相匹配DOM的元素节点的集合。jQuery名字中Query的意义就体现在这里。下面我们来分析一下Sizzle构造器函数。该函数是整个Sizzle引擎的入口。

广州网站建设,网站建设,广州网页设计,广州网站设计
  1. var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][ ^'"]*['"]|[^[\]'"]+) +\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,  
  2.     done = 0,  
  3.     toString = Object.prototype.toString;  
  4. /* 

上边这个正则表达式比较复杂,通过逐层分解,我们可以看到它的作用

首先,可以把整个正则表达式切分为两大块


  1. 第一部分:((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]| [^[\]]+)+\]|\\.|[^ >+~, (\[]+)+|[>+~]]  
  2. 第二部分: (\s*,\s*)?  
  3. 第一部分可以以|(表示或的意思)为分界符做进一步的切分。则切分后的正则表达式如下所示  
  4. /    //正则表达式起始符  
  5.  (    //第一个子表达式  
  6.     (?:\((?:\([^()]+\)    //匹配伪类选择符  
  7.     |[^()]+)+\)    //匹配函数式选择符  
  8.     |\[(?:\[[^[\]]*\]     //匹配属性选择符  
  9.     |['"][^'"]*['"]    //匹配属性选择符  
  10.     |[^[\]'"]+)+\]    //匹配属性选择符  
  11.     |\\.    //匹配Class选择符  
  12.     |[^ >+~,(\[\\]+)+    //匹配关系选择符  
  13.     |[>+~]    //匹配关系选择符  
  14.  )  
  15.  (\s*,\s*)    //匹配选择符组中间的分隔符  
  16.  ?     //非贪婪模式匹配  
  17. /    //正则表达式终止符  
  18. g    //正则表达式属性,全局匹配  
  19. /*  
  20. // Sizzle选择器引擎构造器函数  
  21. //参数说明:  
  22. // selector:选择器字符串  
  23. // context:上下文  
  24. // results:结果集  
  25. // seed:种子  
  26. var Sizzle = function(selector, context, results, seed) {  
  27.     resultsresults = results || [];    //设置默认结果集为空  
  28.     contextcontext = context || document;     //设置上下文为document对象  
  29.     //如果上下文不是元素和文档对象,则返回空集合  
  30.     if ( context.nodeType !== 1 && context.nodeType !== 9 )  
  31.         return [];  
  32.     //如果选择器参数不存在,或者不为字符串类型,则返回默认结果集  
  33.     if ( !selector || typeof selector !== "string" ) {  
  34.         return results;  
  35.     }  
  36.     //初始化变量  
  37.     var parts = [], m, set, checkSet, check, mode, extra, prune = true;  
  38.     // 重置chunker 正则表达式匹配的起始位置为开始位置  
  39.     chunker.lastIndex = 0;  
  40.     //匹配选择符字符串,如果存在则执行下面操作  
  41.     while ( (m = chunker.exec(selector)) !== null ) {  
  42.         parts.push( m[1] );    //存储匹配的字符串信息  
  43.         //如果是选择符组,则获取后半部分  
  44.         if ( m[2] ) {  
  45.             extra = RegExp.rightContext;  
  46.             break;  
  47.         }  
  48.     }  
  49.     //Expr和Sizzle.selector指向同一个对象,这个选择器对象与老版本不一样,  
  50.     //放弃了if else语句判断,全部使用正则表达式进行处理,执行效率提高了很多,  
  51.     //具体代码参阅Expr对象。  
  52.     //POS:正则表达式/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,  
  53.     //下面代码判断选择符字符串中是否存在特殊函数  
  54.     if ( parts.length > 1 && origPOS.exec( selector ) ) {  
  55.         //relative是函数对象,封装了+>~函数,表示typeof Expr.relative[ parts[0] ] ==Function  
  56.         if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {  
  57.             set = posProcess( parts[0] + parts[1], context );  
  58.         } else {  
  59.             set = Expr.relative[ parts[0] ] ?  
  60.                 [ context ] :  
  61.                 Sizzle( parts.shift(), context );  
  62.             //如果匹配到>+~,过滤上下文,去掉选择器中符号,再分析选择器  
  63.             while ( parts.length ) {  
  64.                 selector = parts.shift();  
  65.                 if ( Expr.relative[ selector ] )  
  66.                     selector += parts.shift();  
  67.                 set = posProcess( selector, set );  
  68.             }  
  69.         }  
  70.     } else {  
  71.         //执行种子操作  
  72.         var ret = seed ?  
  73.             { expr: parts.pop(), set: makeArray(seed) } :  
  74.             Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );  
  75.         set = Sizzle.filter( ret.expr, ret.set );  
  76.         if ( parts.length > 0 ) {  
  77.             checkSet = makeArray(set);  
  78.         } else {  
  79.             prune = false;  
  80.         }  
  81.         while ( parts.length ) {  
  82.             var cur = parts.pop(), pop = cur;  
  83.             if ( !Expr.relative[ cur ] ) {  
  84.                 cur = "";  
  85.             } else {  
  86.                 pop = parts.pop();  
  87.             }  
  88.             if ( pop == null ) {  
  89.                 pop = context;  
  90.             }  
  91.             Expr.relative[ cur ]( checkSet, pop, isXML(context) );  
  92.         }  
  93.     }  
  94.     //设置默认值  
  95.     if ( !checkSet ) {  
  96.         checkSet = set;  
  97.     }  
  98.     //抛出异常  
  99.     if ( !checkSet ) {  
  100.         throw "Syntax error, unrecognized expression: " + (cur || selector);  
  101.     }  
  102.     //如果检测到选项checkSet是数组,则执行下面操作  
  103.     if ( toString.call(checkSet) === "[object Array]" ) {  
  104.         //如果checkSet没有包含set选项值  
  105.         if ( !prune ) {  
  106.             //则把checkSet推入到结果集中  
  107.             results.push.apply( results, checkSet );  
  108.         } else if ( context.nodeType === 1 ) {    //如果上下文是元素类型的对象  
  109.             for ( var i = 0; checkSet[i] != null; i++ ) {     //则遍历检测选项集,然后把set推入结果集中  
  110.                 if ( checkSet[i] && (checkSet[i] === true ||  checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {  
  111.                     results.push( set[i] );  
  112.                 }  
  113.             }  
  114.         } else {  
  115.             //则遍历检测选项集,然后把set推入结果集中  
  116.             for ( var i = 0; checkSet[i] != null; i++ ) {  
  117.                 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {  
  118.                     results.push( set[i] );  
  119.                 }  
  120.             }  
  121.         }  
  122.     } else {  
  123.         //把结果集与检测选项组合并为数组  
  124.         makeArray( checkSet, results );  
  125.     }  
  126.     //处理组选择器中下一个选择器  
  127.     if ( extra ) {  
  128.         //把后半部分选择器字符串再次传递给构造器,执行下一次匹配处理  
  129.         Sizzle( extra, context, results, seed );  
  130.         //如果存在排序函数,则调用它对结果集进行排序  
  131.         if ( sortOrder ) {  
  132.             hasDuplicate = false;    //指示已经排序  
  133.             results.sort(sortOrder);     //排序结果集  
  134.             //如果没有排序,则对结果集进行重排  
  135.             if ( hasDuplicate ) {  
  136.                 for ( var i = 1; i < results.length; i++ ) {  
  137.                     if ( results[i] === results[i-1] ) {  
  138.                         results.splice(i--, 1);  
  139.                     }  
  140.                 }  
  141.             }  
  142.         }  
  143.     }  
  144.     //返回匹配的结果集  
  145.     return results;  
  146. }; 

广州网站建设,网站建设,广州网页设计,广州网站设计
标签:
飞机