jQuery选择器源码解读(六):Sizzle选择器匹配逻辑分析


Posted in Javascript onMarch 31, 2015

近期看了一些网上关于Sizzle的分析文章,就匹配次序往往就说使用了从右到左的逆向匹配法,但是具体如何并没有详细介绍,或者就像我之前的几篇文章一样,就代码一行一行做详细介绍,但缺乏整体概念,这里就jQuery-1.10.2版本的Sizzle的匹配逻辑(预编译结果)做一整体说明,这里就不谈过多的细节了。

Sizzle的匹配过程采用的是以从右到左的逆向匹配法为基础的改进版本,因为HTML的搜索毕竟和文本匹配有差异,它有自己独特的一面,所以,需要针对HTML的搜索进行优化。在此先申明一点,下面所说的关系选择器是指W3C中的Combinator选择器,因本人觉得用关系选择器这个名字要比其它更加贴近实际意义,故用此命名。

1、简单介绍一下Sizzle编译执行的两个主要函数:

a) matcherFromTokens——针对一个块选择器生成执行函数,所谓块选择器就是不包含逗号分隔的选择器字符串。

b) matcherFromGroupMatchers——将不同的块选择器生成的最终执行函数,该函数还负责将最终结果过滤掉重复对象。

2、matcherFromTokens函数针对不同类型的选择器产生不同的执行函数。若包含伪类,则返回setMatcher,否则返回的是elementMatcher,代码通过鉴别matcher是否包含expando属性来区别setMatcher和elementMatcher:

a) 针对非伪类且非关系选择器,直接从左到右依次生成执行函数,各函数作为同一个matchers数组的不同元素存在。

b) 针对关系选择器,将会把之前生成的matchers压入一个新的matchers数组中。

c) 针对伪类选择器,将通过setMatcher函数生成一个执行函数,调用setMatcher时,依次传入6个参数,分别是preFilter, selector, matcher, postFilter, postFinder, postSelector。

      preFilter是在执行setMatcher函数之前已生成的matchers数组经elementMatcher函数加工过的最终函数,elementMatcher(matchers)将返回一个从后向前依次执行每一个matchers元素函数的新函数;。

      selector是matchers对应的选择器字符串;

      matcher是伪类自身的匹配函数;

      postFilter是伪类之后,到第一个伪类或关系符之间的选择器字符串对应的匹配函数,它是嵌套调用matcherFromTokens函数的返回结果;

      postFinder是postFilter对应选择器之后的所有选择器生成的匹配函数,同样也是通过嵌套调用matcherFromTokens函数的返回结果;

      postSelector是postFinder对应的选择器字符串。

d) 若选择器字符串中没有伪类,那么,将返回elementMatcher(matchers)生成的最终匹配函数。

从上面的介绍可以看出,生成的执行函数之间存在着嵌套关系,简单的讲就是setMatcher包含matchers,关系选择器匹配函数包含非伪类且非关系选择器匹配函数。

3、执行过程的介绍:

a) 执行块选择器的执行函数:

      针对elementMatcher,从外到里从后到前依次执行,即从最外层数组到最里层数组依次执行,同一个数组中,从最后一个元素到第一个元素依次执行。

      针对setMatcher,先依据preFilter和selector获得匹配结果;然后执行matcher函数获取匹配结果;之后,执行postFilter函数,最后,依据postFinder和postSelector获取匹配结果。

c) 依次执行每个块选择器的执行函数后,过滤掉重复数据,并返回结果。

看了上述大致过程,再去看各方法的详细介绍应该比较容易理解了,当然在这里没有谈到一些细节,例如初始结果集(seed)的生成及由此带来的函数执行逻辑细节上的差异等。

Javascript 相关文章推荐
JavaScript中为元素加上name属性的方法
May 09 Javascript
『jQuery』取指定url格式及分割函数应用
Apr 22 Javascript
jquery.post用法之type设置问题
Feb 24 Javascript
javascript实例--教你实现扑克牌洗牌功能
May 15 Javascript
JavaScript中的Object对象学习教程
May 20 Javascript
你不需要jQuery(三) 新AJAX方法fetch()
Jun 14 Javascript
jQuery实现带延时功能的水平多级菜单效果【附demo源码下载】
Sep 21 Javascript
angular.js指令中的controller、compile与link函数的不同之处
May 10 Javascript
zTree 树插件实现全国五级地区点击后加载的示例
Feb 05 Javascript
vue组件jsx语法的具体使用
May 21 Javascript
vue3.0 搭建项目总结(详细步骤)
May 20 Javascript
js实现的在本地预览图片功能示例
Nov 09 Javascript
jQuery选择器源码解读(五):tokenize的解析过程
Mar 31 #Javascript
JavaScript制作windows经典扫雷小游戏
Mar 31 #Javascript
jQuery选择器源码解读(四):tokenize方法的Expr.preFilter
Mar 31 #Javascript
JavaScript制作简易的微信打飞机
Mar 31 #Javascript
JS获取表格内指定单元格html内容的方法
Mar 31 #Javascript
JS实现为表格动态添加标题的方法
Mar 31 #Javascript
JS实现从表格中动态删除指定行的方法
Mar 31 #Javascript
You might like
劣质的PHP代码简化
2010/02/08 PHP
php模板中出现空行解决方法
2011/03/08 PHP
php和jquery实现地图区域数据统计展示数据示例
2014/02/12 PHP
用PHP代码给图片加水印
2015/07/01 PHP
PHP生成各种常见验证码和Ajax验证过程
2016/01/10 PHP
让你的PHP7更快之Hugepage用法分析
2016/05/31 PHP
js的压缩及jquery压缩探讨(提高页面加载性能/保护劳动成果)
2013/01/29 Javascript
JavaScript获取Url里的参数
2014/12/18 Javascript
JS动态修改图片的URL(src)的方法
2015/04/01 Javascript
日常收集整理的JavaScript常用函数方法
2015/12/10 Javascript
ES6所改良的javascript“缺陷”问题
2016/08/23 Javascript
vue如何引用其他组件(css和js)
2017/04/13 Javascript
JavaScript 中的12种循环遍历方法【总结】
2018/05/31 Javascript
vue js秒转天数小时分钟秒的实例代码
2018/08/08 Javascript
vue-cli创建的项目中的gitHooks原理解析
2020/02/14 Javascript
vue2.0 watch里面的 deep和immediate用法说明
2020/10/30 Javascript
Python splitlines使用技巧
2008/09/06 Python
Python简单生成8位随机密码的方法
2017/05/24 Python
python文本数据相似度的度量
2018/03/12 Python
Pandas 合并多个Dataframe(merge,concat)的方法
2018/06/08 Python
详解python websocket获取实时数据的几种常见链接方式
2019/07/01 Python
python画图把时间作为横坐标的方法
2019/07/07 Python
Python BeautifulSoup [解决方法] TypeError: list indices must be integers or slices, not str
2019/08/07 Python
new_zeros() pytorch版本的转换方式
2020/02/18 Python
python 动态绘制爱心的示例
2020/09/27 Python
IE矩阵Matrix滤镜旋转与缩放及如何结合transform
2012/11/29 HTML / CSS
新大陆软件面试题
2016/11/24 面试题
linux面试题参考答案(5)
2016/11/05 面试题
Linux文件系统类型
2012/02/15 面试题
商务英语专业自荐信
2013/10/14 职场文书
聘用意向书范本
2014/04/01 职场文书
信息管理专业自荐书
2014/06/05 职场文书
销售行政专员岗位职责
2014/06/10 职场文书
节电标语大全
2014/06/23 职场文书
2014副局长群众路线对照检查材料思想汇报
2014/09/22 职场文书
redis客户端实现高可用读写分离的方式详解
2021/07/04 Redis