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

      1 //得到由选择器生成的token对象的数组(下面的groups)
      2 //Sizzle的Token格式如下 :{value:'匹配到的字符串', type:'对应的Token类型', matches:'正则匹配到的一个结构'}
      3 //比如"title,div > :nth-child(even)"解析下面的符号流
      4     // [ [{value:"title",type:"TAG",matches:["title"]}],
      5     //   [{value:"div",type:["TAG",matches:["div"]},
      6     //    {value:">", type: ">"},
      7     //    {value:":nth-child(even)",type:"CHILD",matches:["nth",
      8     //     "child","even",2,0,undefined,undefined,undefined]}
      9     //   ]
     10     // ]
     11     //有多少个并联选择器,里面就有多少个数组,数组里面是拥有value与type的对象
     12 
     13 //tokenize两个作用:1.解析选择器;2.将解析结果存入缓存
     14 tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
     15     var matched, match, tokens, type,
     16         soFar, groups, preFilters,
     17         cached = tokenCache[ selector + " " ];
     18     //这里的soFar是表示目前还未分析的字符串剩余部分
     19 
     20     //如果tokenCache中已经有selector了,则直接拿出来就好了
     21     if ( cached ) {
     22         return parseOnly ? 0 : cached.slice( 0 );
     23     }
     24 
     25     soFar = selector;
     26     groups = [];
     27 
     28     //这里的预处理器为了对匹配到的Token适当做一些调整
     29     preFilters = Expr.preFilter;
     30 
     31     //循环处理字符串
     32     while ( soFar ) {
     33 
     34         // Comma and first run
     35         //whitespace = "[\x20\t\r\n\f]";
     36         //rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" );
     37         //!matched:若是第一次执行循环体,则为true;否则为false。 
     38         //这里matched即作为是否第一次执行循环体的标识,
     39         if ( !matched || (match = rcomma.exec( soFar )) ) {
     40             if ( match ) {
     41                 // Don't consume trailing commas as valid
     42                 //去掉sofar中第一个的无用",",比如",div,#id"中的第一个","
     43                 //举个例子,"div.news,span.closed"
     44                 //在解析过程中,首先由后续代码解析完毕div.news,剩下",span.closed"
     45                 //在循环体内执行到这里时,将逗号及之前之后连续的空白(match[0])删除掉, 
     46                 //使soFar变成"span.closed",继续执行解析过程
     47                 soFar = soFar.slice( match[0].length ) || soFar;
     48             }
     49             //往规则组里边压入一个Token序列,目前Token序列还是空的
     50             groups.push( (tokens = []) );
     51         }
     52 
     53         matched = false;
     54 
     55         // Combinators
     56         //rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"), 
     57         //rcombinators用来匹配四种关系符,即>+~和空白
     58         if ( (match = rcombinators.exec( soFar )) ) {
     59             // 举个例子: 
     60             // 若soFar = " + .div"; 
     61             // 执行match = rcombinators.exec(soFar)后, 
     62             // match[0] = " + ",而match[1]="+"; 
     63             // 执行完matched = match.shift()后, 
     64             // matched=" + ",而match[0]="+"; 
     65             matched = match.shift();
     66             tokens.push({
     67                 value: matched,
     68                 // Cast descendant combinators to space
     69                 type: match[0].replace( rtrim, " " )
     70             });
     71             soFar = soFar.slice( matched.length );
     72         }
     73 
     74         // Filters
     75         //下面通过for语句对soFar逐一匹配ID、TAG、CLASS、CHILD、ATTR、PSEUDO类型的选择器 
     76         // 若匹配到了,则先调用该类型选择器对应的预过滤函数, 
     77         // 然后,将结果压入tokens数组,继续本次循环。
     78         for ( type in Expr.filter ) {
     79             //  match = matchExpr[type].exec(soFar):对soFar调用type类型的正则表达式对soFar进行匹配 
     80             // 并将匹配结果赋予match。若未匹配到数据,则match为null。 
     81             // !preFilters[type]:若不存在type类型的预过滤函数,则为true 
     82             // match = preFilters[type](match):执行预过滤,并将结果返回给match
     83             if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
     84                 (match = preFilters[ type ]( match ))) ) {
     85                 // 将match[0]移除match数组,同时将它赋予matched  
     86                 matched = match.shift();
     87                 // 将匹配结果压入tokens数组中
     88                 tokens.push({
     89                     value: matched,
     90                     type: type,
     91                     matches: match
     92                 });
     93                 // 将匹配结果之后的字符串赋予soFar,继续解析
     94                 soFar = soFar.slice( matched.length );
     95             }
     96         }
     97 
     98         //matched为false,说明本次循环没有效的选择器(包括关系符和id、class等类型选择器)
     99         if ( !matched ) {
    100             break;
    101         }
    102     }
    103 
    104     // Return the length of the invalid excess
    105     // if we're just parsing
    106     // Otherwise, throw an error or return tokens
    107     return parseOnly ?
    108         soFar.length :
    109         soFar ?
    110             Sizzle.error( selector ) :
    111             // Cache the tokens
    112             tokenCache( selector, groups ).slice( 0 );
    113 };

    画一张直观图便于理解

    image

  • 相关阅读:
    javascript之数组操作
    python中的类中属性元素加self.和不加self.的区别
    Q查询
    jQuery EasyUI的各历史版本和应用
    了解Entity Framework中事务处理
    C#中Abstract和Virtual的区别
    控制器post参数接收
    存储过程调用存储过程
    表变量、临时表(with as ,create table)
    LINQ TO SQL 实现无限递归查询
  • 原文地址:https://www.cnblogs.com/shytong/p/5336292.html
Copyright © 2011-2022 走看看