//得到由选择器生成的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. MFC中不同对话框间使用SendMessage发送自定义消息的具体实现

    1. 基本知识 SendMessage的基本结构如下: SendMessage(     HWND hWnd,  //消息传递的目标窗口或线程的句柄.     UINT Msg, //消息类别(这里可 ...

  2. Elasticsearch 相关 api 操作

    A. es 操作 1. 检查 es 集群健康状态 2. 获取集群中的节点列表 3. 创建索引 4. 获取索引 5. 索引文档 6. 查询文档 7. 删除索引 8. 更新文档 9. 删除文档 10. 批 ...

  3. 【TFS 2017】使用浏览器上传文件(TFVC)或者编辑代码,错误提示TF14098,需要对文件有PendChange 权限

    从TFS 2015开始,微软在TFS系统中增加了一个非常吸引开发人员的功能,"快速代码编辑器" (Quick Code Editor).使用这个功能,你可以在任何安装了浏览器的设备 ...

  4. DAC--解决windows验证无法登陆的问题

    解决思路: 使用单用户管理员模式启动SQL Server,再使用SQLCMD连接上数据库,此时有sysadmin权限,添加用户并赋予相应权限 1>停止SQL Server服务运行 2>在C ...

  5. NERDTree基本使用教程

    Vim插件之属性目录NERDTree   1.下载安装 下载地址: 官网:http://www.vim.org/scripts/script.php?script_id=1658 GitHib:htt ...

  6. 解决 EntityFrameworkCore 执行 Add-Migration命令提示无法识别转义符的错误

    版本.asp.net core 2.0   EntityFrameworkCore2,0,. 之前执行Add-Migration 命令 提示无法识别的转义序列,各种不成功, 解决办法,找到 项目里面的 ...

  7. EF简易教程,从建表到表间关系

    唐大兵博客 唐大兵的博客里记录了EF Code First从建表到表之间关系的详细内容. 汪杰的博客(EF里一对一.一对多.多对多关系的配置和级联删除) 汪杰的博客更简洁,但不够充实,读懂了唐大兵博客 ...

  8. python小数的进位与舍去

    一.基础知识准备 ​ 奇进偶舍,又称为四舍六入五成双规则.银行进位法(Banker's Rounding),是一种计数保留法,是一种数值修约规则.从统计学的角度,"奇进偶舍"比&q ...

  9. Xcode的多种Build Configuration

    一: 建多个Configuration的目的. 多套域名打包. 1 开发时的域名. 2 内测时的域名. 3 公测时的域名. 4 企业版的域名. 5 APP Store的域名. 通过注释的方式,容易出错 ...

  10. hdoj1575 Tr A(矩阵快速幂)

    简单的矩阵快速幂.最后求矩阵的秩. #include<iostream> #include<cstring> using namespace std; ; int n,k; s ...