zoukankan      html  css  js  c++  java
  • 【jQuery源码】select方法

      1 /**
      2  * select方法是Sizzle选择器包的核心方法之一,其主要完成下列任务: 
      3  * 1、调用tokenize方法完成对选择器的解析 
      4  * 2、对于没有初始集合(即seed没有赋值)且是单一块选择器(即选择器字符串中没有逗号), 
      5  *    完成下列事项: 
      6  *    1) 对于首选择器是ID类型且context是document的,则直接获取对象替代传入的context对象 
      7  *    2) 若选择器是单一选择器,且是id、class、tag类型的,则直接获取并返回匹配的DOM元素 
      8  *    3) 获取最后一个id、class、tag类型选择器的匹配DOM元素赋值给初始集合(即seed变量) 
      9  * 3、通过调用compile方法获取“预编译”代码并执行,获取并返回匹配的DOM元素 
     10  *  
     11  * @param selector 已去掉头尾空白的选择器字符串 
     12  * @param context 执行匹配的最初的上下文(即DOM元素集合)。若context没有赋值,则取document。 
     13  * @param results 已匹配出的部分最终结果。若results没有赋值,则赋予空数组。 
     14  * @param seed 初始集合 
     15  */
     16 select = Sizzle.select = function( selector, context, results, seed ) {
     17     var i, tokens, token, type, find,
     18         compiled = typeof selector === "function" && selector,
     19         //在没有seed的时候,调用tokensize方法进行词法解析,结果放在match中
     20         //seed - 种子合集(搜索器搜到符合条件的标签),放入到这个初始集合seed中
     21         match = !seed && tokenize( (selector = compiled.selector || selector) );
     22 
     23     results = results || [];
     24 
     25     // Try to minimize operations if there is no seed and only one group
     26     //只有一组选择器,也就是选择器中没有逗号
     27     if ( match.length === 1 ) {
     28 
     29         // Take a shortcut and set the context if the root selector is an ID
     30         //创建一个新的集合赋给tokens,确保原有集合不被更改
     31         tokens = match[0] = match[0].slice( 0 );
     32         /* 
     33              * 若选择器是以id类型开始,且第二个是关系符(即+~>或空格), 
     34              * 则获取id所属对象作为context继续完成后续的匹配 
     35              *  
     36              * 此处的条件判断依次为: 
     37              * tokens.length > 2 :若tokens有两个以上的选择器 
     38              * (token = tokens[0]).type === "ID" :第一个选择器的类型为ID(即以#开头的), 
     39              * support.getById :支持getElementById函数 
     40              * context.nodeType === 9 :context对象是document 
     41              * documentIsHTML :当前处理的是HTML代码 
     42              * Expr.relative[tokens[1].type] :第二个tokens元素是一个关系(即+~>或空格) 
     43              * 在满足上面所有条件的情况下,执行if内的语句体 
     44         */  
     45         if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
     46                 support.getById && context.nodeType === 9 && documentIsHTML &&
     47                 Expr.relative[ tokens[1].type ] ) {
     48 
     49             //查找id为matches[1]的元素
     50             context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
     51             if ( !context ) {
     52                 return results;
     53 
     54             // Precompiled matchers will still verify ancestry, so step up a level
     55             } else if ( compiled ) {
     56                 context = context.parentNode;
     57             }
     58 
     59             //去掉selector中第一个选择器
     60             selector = selector.slice( tokens.shift().value.length );
     61         }
     62 
     63         // Fetch a seed set for right-to-left matching
     64         //其中: "needsContext"= new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\(" + whitespace + "*((?:-\d)?\d*)" + whitespace + "*\)|)(?=[^-]|$)", "i" )
     65         //即是表示如果没有一些结构伪类,这些是需要用另一种方式过滤,在之后文章再详细剖析。
     66         //那么就从最后一条规则开始,先找出seed集合
     67         i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
     68         while ( i-- ) {
     69             token = tokens[i];
     70 
     71             // Abort if we hit a combinator
     72             //如果遇到了关系选择器则终止循环,> + ~ 空
     73             if ( Expr.relative[ (type = token.type) ] ) {
     74                 break;
     75             }
     76             /*
     77                 先看看有没有搜索器find,搜索器就是浏览器一些原生的取DOM接口,简单的表述就是以下对象了
     78                 Expr.find = {
     79                     'ID'    : context.getElementById,
     80                     'CLASS' : context.getElementsByClassName,
     81                     'NAME'  : context.getElementsByName,
     82                     'TAG'   : context.getElementsByTagName
     83                 }
     84             */
     85             if ( (find = Expr.find[ type ]) ) {
     86                 // Search, expanding context for leading sibling combinators
     87                 // 尝试一下能否通过这个搜索器搜到符合条件的初始集合seed
     88                 if ( (seed = find(
     89                     token.matches[0].replace( runescape, funescape ),
     90                     rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
     91                 )) ) {
     92 
     93                     // If seed is empty or no tokens remain, we can return early
     94                     //删除这条标签
     95                     tokens.splice( i, 1 );
     96                     selector = seed.length && toSelector( tokens );
     97                     //若当前选择器是否为空,把seed推入results,返回结果
     98                     if ( !selector ) {
     99                         push.apply( results, seed );
    100                         return results;
    101                     }
    102                     //已经找到了符合条件的seed集合,此时前边还有其他规则,跳出去
    103                     break;
    104                 }
    105             }
    106         }
    107     }
    108 
    109     // Compile and execute a filtering function if one is not provided
    110     // Provide `match` to avoid retokenization if we modified the selector above
    111     ( compiled || compile( selector, match ) )(
    112         seed,
    113         context,
    114         !documentIsHTML,
    115         results,
    116         rsibling.test( selector ) && testContext( context.parentNode ) || context
    117     );
    118     return results;
    119 };
  • 相关阅读:
    【leetcode】106. Construct Binary Tree from Inorder and Postorder Traversal
    【leetcode】105. Construct Binary Tree from Preorder and Inorder Traversal
    【leetcode】236. Lowest Common Ancestor of a Binary Tree
    【leetcode】235. Lowest Common Ancestor of a Binary Search Tree
    【leetcode】352. Data Stream as Disjoint Intervals
    【leetcode】897. Increasing Order Search Tree
    【leetcode】900. RLE Iterator
    BEC listen and translation exercise 26
    BEC listen and translation exercise 25
    BEC listen and translation exercise 24
  • 原文地址:https://www.cnblogs.com/shytong/p/5351656.html
Copyright © 2011-2022 走看看