在Sizzle里,大体思路,当为复合选择器时,判断是否支持querySeletorAll,如果不支持则调用自写方法select。

select的功能十分冗长,下面先分析tokenize

在tokenize函数的作用是将形如'ul.topnav > li,div'的选择器解析为

[
[{value:'ul',type:"TAG",matches:['ul']},{value:'.topnav',type:"CLASS",matches:['topnav']},{value:' > ',type:">"},{value:'li',type:"TAG",matches:['li']}],
[{value:'div',type:"TAG",matches:['div']}]
]

每个逗号解析为一个数组,表示一个独立选择器项,每个独立选择器项的选择关系按照CLASS,TAG,ID和关系解析成如上格式。

这种解析的类型是下面进行查找元素的固定格式,先不考虑后面,我们先分析tokenize的实现。

//缓存函数创建函数
var createCache = function(){
//缓存函数共用数组
var keys = [];
return function cache(name,value){
// 当长度大于某常数时,清除老元素,插入新元素
if( keys.push( name ) > 1){
delete cache[ keys.shift() ]
};
return cache[name] = value;
};
}
//缓存函数对象
//这是一个方法,通过这个方法可以将缓存数据保存在这个函数(也是对象)里。
var tokenCache = createCache();
//简易正则过滤对象
var filter = {
TAG: /^(\w+)/,
ID: /^#(\w+)/,
CLASS: /^\.(\w+)/
}
//关系匹配正则
var relation = /^\s*([\>\+\~]|^\s)\s*/;
//逗号正则
var comma = /^\,/;
function tokenize(selector){
var cached = tokenCache[selector];
//缓存中有结果,直接返回
if(cached){
return cached;
}
// 循环条件
var sofar = selector,
// 结果数组
groups = [],
// 匹配参数
matched,
// 一个独立选择器项
token = [],
//辅助参数正则匹配结果
match;
//循环解析选择器
while(sofar){
//首次默认创建一个单独选择器项
//之后通过判断逗号创建
if(!matched || (match = comma.exec(sofar)) ){
if(match){
//保存未解析的选择器
sofar = sofar.slice(match[0].length);
}
groups.push(token = []);
}
//每次循环设置辅助匹配参数为false,如果之后仍无匹配不存在通过break跳出循环
matched = false;
//匹配关系>等
//解析保存结果
if(match = relation.exec(sofar)){
matched = match.shift();
token.push({
value: matched,
type: match[0].replace( /\s+/g, " " )
})
sofar = sofar.slice(matched.length)
}
//匹配选择器CLASS,TAG,ID
//解析保存结果
for(var type in filter){
if(match = filter[type].exec(sofar)){
matched = match.shift();
token.push({
value: matched,
type: type,
matches: match
})
sofar = sofar.slice(matched.length)
}
}
//没有跳出循环。
if ( !matched ) {
break;
} }
//缓存结果并返回
return (tokenCache(selector,groups));
}
console.log(tokenize('ul.topnav > li,div'))
console.log(tokenize('a li'))

这是我模拟输入输出结果写出的函数,jQuery源码中在实现主要功能的基础上进行了大量兼容处理。

缓存在jQuery里面非常常用,在这里重新说一遍基本思路是,将函数输入值key,和输出值保存于缓存对象中,等到下次调用函数,如果缓存对象中有值,则直接读取。

本例的缓存略微复杂,它是利用函数将缓存数据保存于同名对象中。又,作者希望几种缓存共用长度,在这里用了创建缓存函数的函数。

Sizzle之tokenize的更多相关文章

  1. sizzle分析记录:词法分析器(tokenize)

    词法分析器(tokenize)? 词法分析器又称扫描器.词法分析是指将我们编写的文本代码流解析为一个一个的记号,分析得到的记号以供后续语法分析使用. sizzle引入了tokenize这个概念,意义? ...

  2. jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——编译原理

    这一节要分析的东东比较复杂,篇幅会比较大,也不知道我描述后能不能让人看明白.这部分的源码我第一次看的时候也比较吃力,现在重头看一遍,再分析一遍,看能否查缺补漏. 看这一部分的源码需要有一个完整的概念后 ...

  3. JQuery Sizzle引擎源代码分析

    最近在拜读艾伦在慕课网上写的JQuery课程,感觉在国内对JQuery代码分析透彻的人没几个能比得过艾伦.有没有吹牛?是不是我说大话了? 什么是Sizzle引擎? 我们经常使用JQuery的选择器查询 ...

  4. jQuery 2.0.3 源码分析Sizzle引擎 - 词法解析

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 浏览器从下载文档到显示页面的过程是个复杂的过程,这里包含了重绘和重排.各家浏览器引擎的工作原理略有差别,但也有一定规则. 简 ...

  5. jQuery 2.0.3 源码分析Sizzle引擎 - 解析原理

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 先来回答博友的提问: 如何解析 div > p + div.aaron input[type="checkb ...

  6. jQuery 2.0.3 源码分析Sizzle引擎 - 编译函数(大篇幅)

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 从Sizzle1.8开始,这是Sizzle的分界线了,引入了编译函数机制 网上基本没有资料细说这个东东的,sizzle引入这 ...

  7. jQuery 2.0.3 源码分析Sizzle引擎 - 超级匹配

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 通过Expr.find[ type ]我们找出选择器最右边的最终seed种子合集 通过Sizzle.compile函数编译器 ...

  8. 解密jQuery内核 Sizzle引擎筛选器 - 位置伪类(一)

    本章开始分析过滤器,根据API的顺序来 主要涉及的知识点 jQuery的组成 pushStack方法的作用 sizzle伪类选择器 首页我们知道jQuery对象是一个数组对象 内部结构 jQuery的 ...

  9. jQuery 2.0.3 源码分析Sizzle引擎 - 高效查询

    为什么Sizzle很高效? 首先,从处理流程上理解,它总是先使用最高效的原生方法来做处理 HTML文档一共有这么四个API: getElementById 上下文只能是HTML文档 浏览器支持情况:I ...

随机推荐

  1. C指针

    1,每行最大长度,处理的最大列号; preprocessor directives,preprocessor,预处理器读入源代码,根据预处理指令对其进行修改,把修改后 的源代码递交给编译器; 预处理器 ...

  2. K-近邻算法python实现

    内容主要来源于机器学习实战这本书.加上自己的理解. 1.KNN算法的简单描写叙述 K近期邻(k-Nearest Neighbor.KNN)分类算法能够说是最简单的机器学习算法了. 它採用測量不同特征值 ...

  3. Flash Recovery Area 的备份

    Flash Recovery Area 的备份 备份命令是Flash recovery Area,该命令是Oracle 10g以后才有的.10g引进了flash recovery area,同时在rm ...

  4. Kafka的可靠性问题

    a. Producer到broker 把request.required.acks设为1,丢会重发,丢的概率很小 b. Broker b.1 对于broker,落盘的数据,除非磁盘坏了,不会丢的 b. ...

  5. T-SQL存储过程

    存储过程(procedure)就是一个函数,完成一段sql代码的封装,实现代码的重用.    优点:         1.比使用DotNet直接写Sql脚本执行少了一块解析编译的过程.效率更快一点点. ...

  6. css中关于transform、transition、animate的区别

    写动画经常会用到这几个属性,他们之间有什么区别呢? 1.transform 每每演示transform属性的,看起来好像都是带动画.这使得小部分直觉化思维的人(包括我)认为transform属性是动画 ...

  7. pixel像素与物理像素

  8. 彻底解决TAP(点透)提升移动端点击响应速度

    使用fastclick 尼玛使用太简单了,直接一句: FastClick.attach(document.body); 于是所有的click响应速度直接提升,刚刚的!什么input获取焦点的问题也解决 ...

  9. Broadcast详解

    今天闲来无事,研究了下Android的Broadcast,发现Broadcast在Android系统中担任着很艰巨的角色. Broadcast是Android的四大组件之一:Broadcast分为普通 ...

  10. [IOS]图标尺寸

    最新参考网址:https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/Ico ...