//得到由选择器生成的token对象的数组(下面的groups)
//Sizzle的Token格式如下 :{value:'匹配到的字符串', type:'对应的Token类型', matches:'正则匹配到的一个结构'}
//比如"title,div > :nth-child(even)"解析下面的符号流
// [ [{value:"title",type:"TAG",matches:["title"]}],
// [{value:"div",type:["TAG",matches:["div"]},
// {value:">", type: ">"},
// {value:":nth-child(even)",type:"CHILD",matches:["nth",
// "child","even",2,0,undefined,undefined,undefined]}
// ]
// ]
//有多少个并联选择器,里面就有多少个数组,数组里面是拥有value与type的对象 //tokenize两个作用:1.解析选择器;2.将解析结果存入缓存
tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
var matched, match, tokens, type,
soFar, groups, preFilters,
cached = tokenCache[ selector + " " ];
//这里的soFar是表示目前还未分析的字符串剩余部分 //如果tokenCache中已经有selector了,则直接拿出来就好了
if ( cached ) {
return parseOnly ? 0 : cached.slice( 0 );
} soFar = selector;
groups = []; //这里的预处理器为了对匹配到的Token适当做一些调整
preFilters = Expr.preFilter; //循环处理字符串
while ( soFar ) { // Comma and first run
//whitespace = "[\\x20\\t\\r\\n\\f]";
//rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" );
//!matched:若是第一次执行循环体,则为true;否则为false。
//这里matched即作为是否第一次执行循环体的标识,
if ( !matched || (match = rcomma.exec( soFar )) ) {
if ( match ) {
// Don't consume trailing commas as valid
//去掉sofar中第一个的无用",",比如",div,#id"中的第一个","
//举个例子,"div.news,span.closed"
//在解析过程中,首先由后续代码解析完毕div.news,剩下",span.closed"
//在循环体内执行到这里时,将逗号及之前之后连续的空白(match[0])删除掉,
//使soFar变成"span.closed",继续执行解析过程
soFar = soFar.slice( match[0].length ) || soFar;
}
//往规则组里边压入一个Token序列,目前Token序列还是空的
groups.push( (tokens = []) );
} matched = false; // Combinators
//rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"),
//rcombinators用来匹配四种关系符,即>+~和空白
if ( (match = rcombinators.exec( soFar )) ) {
// 举个例子:
// 若soFar = " + .div";
// 执行match = rcombinators.exec(soFar)后,
// match[0] = " + ",而match[1]="+";
// 执行完matched = match.shift()后,
// matched=" + ",而match[0]="+";
matched = match.shift();
tokens.push({
value: matched,
// Cast descendant combinators to space
type: match[0].replace( rtrim, " " )
});
soFar = soFar.slice( matched.length );
} // Filters
//下面通过for语句对soFar逐一匹配ID、TAG、CLASS、CHILD、ATTR、PSEUDO类型的选择器
// 若匹配到了,则先调用该类型选择器对应的预过滤函数,
// 然后,将结果压入tokens数组,继续本次循环。
for ( type in Expr.filter ) {
// match = matchExpr[type].exec(soFar):对soFar调用type类型的正则表达式对soFar进行匹配
// 并将匹配结果赋予match。若未匹配到数据,则match为null。
// !preFilters[type]:若不存在type类型的预过滤函数,则为true
// match = preFilters[type](match):执行预过滤,并将结果返回给match
if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
(match = preFilters[ type ]( match ))) ) {
// 将match[0]移除match数组,同时将它赋予matched
matched = match.shift();
// 将匹配结果压入tokens数组中
tokens.push({
value: matched,
type: type,
matches: match
});
// 将匹配结果之后的字符串赋予soFar,继续解析
soFar = soFar.slice( matched.length );
}
} //matched为false,说明本次循环没有效的选择器(包括关系符和id、class等类型选择器)
if ( !matched ) {
break;
}
} // Return the length of the invalid excess
// if we're just parsing
// Otherwise, throw an error or return tokens
return parseOnly ?
soFar.length :
soFar ?
Sizzle.error( selector ) :
// Cache the tokens
tokenCache( selector, groups ).slice( 0 );
};

画一张直观图便于理解

 

【jQuery源码】tokenize方法的更多相关文章

  1. jQuery源码——.html()方法原理解析

    在将字符串转化为html碎片时,一般会将字符串作为容器的innerHTML属性赋值.但innerHTML有很多局限性,比如我们想转化的字符串中有<script>标签并且包含一个立即执行的函 ...

  2. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  3. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  4. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  5. Jquery源码学习(第一天)

    jQuery是面向对象的设计通过window.$ = window.jQuery = $; 向外提供接口,将$挂在window下,外部就可以使用$和jQuery $("#div1" ...

  6. jQuery源码 Ajax模块分析

    写在前面: 先讲讲ajax中的相关函数,然后结合函数功能来具体分析源代码. 相关函数: >>ajax全局事件处理程序 .ajaxStart(handler) 注册一个ajaxStart事件 ...

  7. jQuery源码:从原理到实战

    jQuery源码:从原理到实战 jQuery选择器对象 $(".my-class"); document.querySelectorAll*".my-class" ...

  8. 【菜鸟学习jquery源码】数据缓存与data()

    前言 最近比较烦,深圳的工作还没着落,论文不想弄,烦.....今天看了下jquery的数据缓存的代码,参考着Aaron的源码分析,自己有点理解了,和大家分享下.以后也打算把自己的jquery的学习心得 ...

  9. 从jquery源码中看类型判断和数组的一些操作

    在深入看jquery源码中,大家会发现源码写的相当巧妙.那我今天也通过几个源码中用到的技巧来抛砖引玉,希望大家能共同研究源码之精华,不要囫囵吞枣. 1.将类数组转化成数组 我想大家首先想到的方法是fo ...

  10. 读艾伦的jQuery的无new构建,疑惑分析——jquery源码学习一

    背景: 有心学习jquery源码,苦于自己水平有限,若自己研究,耗时耗力,且读懂之日无期. 所以,网上寻找高手的源码分析.再经过自己思考,整理,验证.以求有所收获. 此篇为读高手艾伦<jQuer ...

随机推荐

  1. AE(ArcEngine)定制工具Tool工具箱

    using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServi ...

  2. git提交提示workspace.xml出现conflicted

    问题:在github上管理项目,多次提交以后提交提示workspace.xml出现conflicted原因:Android项目在根目录的.gitignore文件中没有添加.idea文件夹忽略. 解决办 ...

  3. Delphi for iOS开发指南(7):在iOS应用程序中使用WebBrowser组件

    Delphi for iOS开发指南(7):在iOS应用程序中使用WebBrowser组件 在FireMonkey iOS应用程序中使用WebBrowser 在iOS平台上,FireMonkey使用T ...

  4. Spring Boot 应用系列 3 -- Spring Boot 2 整合MyBatis和Druid,多数据源

    本文演示多数据源(MySQL+SQL Server)的配置,并且我引入了分页插件pagehelper. 1. 项目结构 (1)db.properties存储数据源和连接池配置. (2)两个数据源的ma ...

  5. VS版本与系统不兼容问题

    1.VS2012在win7 64位系统安装快结束时报出一个不兼容的错误. 2.这种情况官方给出解决方法: http://www.microsoft.com/en-us/download/details ...

  6. oracle 游标简单案例

    oracle  游标简单案例 一.案例: DECLARE IDO NUMBER; DABH CHAR); t_count ); CURSOR TJ_CURSOR IS SELECT IDO,DABH ...

  7. 【洛谷4719】 动态dp(树链剖分,dp,矩阵乘法)

    前言 其实我只是为了过掉模板而写的ddp,实际应用被吊着锤 Solution 并不想写详细的过程 一句话过程:将子树中轻儿子的贡献挂到这个点上面来 详细版:(引用yyb) 总结一下的话,大致的过程是这 ...

  8. OSLab课堂作业2

      日期:2019/3/23 内容: 实现内容 要求 mysys.c 实现函数mysys,用于执行一个系统命令. mysys的功能与系统函数system相同,要求用进程管理相关系统调用自己实现一遍 使 ...

  9. Flask基础-基础实例

    1. 10行代码的迷你程序 flask项目 from flask import Flask app = Flask(__name__) @app.route("/index") d ...

  10. webpack快速入门——CSS进阶:消除未使用的CSS

    使用PurifyCSS可以大大减少CSS冗余 1.安装 cnpm i purifycss-webpack purify-css --save-dev 2.引入glob,因为我们需要同步检查html模板 ...