Sizzle.filter [ 源代码分析 ]
最近的研究已Sizzle选择,对于原理中我们也不得不佩服!
Sizzle中间filter办法。主要负责元素表达式过滤块的集合,在内部的方法调用Sizzle.selector.fitler滤波操作的操作方法。
Sizzle.filter要点5:
1 使用LeftMatch确定表达式类型。
2 调用Sizzle.selectors.preFilter预过虑函数,运行过滤前的修正。
3 调用Sizzle.selectors.filter[ type ] 中相应的过滤函数,运行过滤操作,假设返回false,刚将元素集合中的相应位置的元素替换为false;
4 删除表达式中已过滤的部分
5 反复1 - 4 步骤
源代码例如以下:
Sizzle.filter = function( expr, set, inplace, not ) {
//expr 块表达式
//set 待过滤的元素集合
//inplace 是否替换,假设为true,那么当set中的元素与expr不匹配时,刚将不匹配的元素替换为false,
//否则。构造新的数组,仅仅保留匹配的元素
//not: 假设为true,则去掉匹配元素,保留不匹配元素。假设为false,则保留匹配元素,去掉不匹配元素
var match, anyFound,
type, found, item, filter, left,
i, pass,
old = expr,
result = [],
curLoop = set,
isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
//while 循环,无限循环用expr过滤set元素,直到expr为空,由于在最后会将已经匹配过的部分删除,所以expr会越来越短
while ( expr && set.length ) {
for ( type in Expr.filter ) {
//这里用来确定表达式类型。依据leftMatch正则
//这里是match正则,LeftMatch仅仅是要该正则加上了前缀和后缀
/*
match: {
ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?
=)\s*(?:(['"])(.*?
)\3|(#?(?
:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
TAG: /^((?
:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?
:[+\-]?\d+|(?
:[+\-]?\d*)?
n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
PSEUDO: /:((?
:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
},
*/
if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
filter = Expr.filter[ type ];
//确定前缀
left = match[1];
anyFound = false;
match.splice(1,1);
//这里官方说是匹配 \\ 假设是 \\ 那么表示后面的元素都是被转义,刚不须要再去过滤,
//只是个人觉得这个地方似乎无效的 left.subster(left.length - 1)
//这个字符的长度仅仅会是1 怎么会和 \\ 相等呢
if ( left.substr( left.length - 1 ) === "\\" ) {
continue;
}
//重置result为空数组,用于缩小候选集,result用来存放通过过滤的元素
if ( curLoop === result ) {
result = [];
}
if ( Expr.preFilter[ type ] ) {
//这里会进行预过滤操作,主要对表达式进行改动正,如转义\\,取出空格等
//针对不同和类型,会有不同的方式,详情能够见preFilter方法
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
/*match:
1 true: 继续须要运行过滤。尚不到运行过虑函数的时候,直接运行continue,不再去调用filter方法。如pos,child
2 false: 已经运行了过滤,缩小了候选集如:CLASS
3 字符串: 修正之后的过滤參数。后面会继续调用相应的过虑函数
*/
if ( !match ) {
anyFound = found = true;
} else if ( match === true ) {
continue;
}
}
//返回的是修正的过滤參数,刚继续运行
if ( match ) {
//遍历候选集中的元素
for ( i = 0; (item = curLoop[i]) != null; i++ ) {
//元素存在
if ( item ) {
//对其进行过滤,返回结果
found = filter( item, match, i, curLoop );
//这里与 not 进行 异或 操作
pass = not ^ found;
//为替换模式,而且found 不为空
if ( inplace && found != null ) {
//假设通过。那么为true
if ( pass ) {
anyFound = true;
} else {
//否则将元素替换为false
curLoop[i] = false;
}
} else if ( pass ) {
//这要须要注意的是既然pass为真了。 那么就不须要推断了found,由于pass为found与not异或的结果
//假设通过了,而且为非替换模式,那么将元素放入到新的数组result中
result.push( item );
anyFound = true;
}
}
}
}
//found不为undefined
if ( found !== undefined ) {
if ( !inplace ) {
//非替换模式,将结果复制给curLoop,
curLoop = result;
}
//删除已经过滤过了的部分表达式
expr = expr.replace( Expr.match[ type ], "" );
//不匹配,返回空
if ( !anyFound ) {
return [];
}
//这里的break,说明已经进行过一次过虑,已经找到相应的type,能够选择跳出当前type的循环,
break;
}
}
}
// 这里主要是匹配,假设最后过滤的表达式没有变化。那么觉得过滤表达式有问题
if ( expr === old ) {
if ( anyFound == null ) {
Sizzle.error( expr );
} else {
break;
}
}
//备份expr,继续循环
old = expr;
}
//返回过滤的结水果
return curLoop;
};
版权声明:本文博主原创文章。转载声明转载地址。
Sizzle.filter [ 源代码分析 ]的更多相关文章
- LAV Filter 源代码分析 4: LAV Video (2)
上一篇文章分析了LAV Filter 中的LAV Video的两个主要的类:CLAVVideo和CDecodeThread.文章:LAV Filter 源代码分析 3: LAV Video (1) 在 ...
- 转:LAV Filter 源代码分析
1: 总体结构 LAV Filter 是一款视频分离和解码软件,他的分离器封装了FFMPEG中的libavformat,解码器则封装了FFMPEG中的libavcodec.它支持十分广泛的视音频格式. ...
- JQuery Sizzle引擎源代码分析
最近在拜读艾伦在慕课网上写的JQuery课程,感觉在国内对JQuery代码分析透彻的人没几个能比得过艾伦.有没有吹牛?是不是我说大话了? 什么是Sizzle引擎? 我们经常使用JQuery的选择器查询 ...
- LAV Filter 源代码分析 3: LAV Video (1)
LAV Video 是使用很广泛的DirectShow Filter.它封装了FFMPEG中的libavcodec,支持十分广泛的视频格式的解码.在这里对其源代码进行详细的分析. LAV Video ...
- Sizzle.selectors.relative [ 源代码分析 ]
1 jQuery 对象Sizzle.selectors.relative中存放了块间关系符和相应的块间关系过滤函数,称为"块间关系过滤函数集" 块间关系符共同拥有4种,其含义和过滤 ...
- ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- 转:SDL2源代码分析
1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...
- 转:RTMPDump源代码分析
0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...
- 转:ffdshow 源代码分析
ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...
随机推荐
- 用KnockoutJS实现ToDoMVC代码分析
体验地址 Knockout 版todo web app在线体验 http://todomvc.com/examples/knockoutjs/ 源码地址 项目源码地址,此地址包含了各种JS框架实现的t ...
- JFinal开发8个常见问题
下面是8个最常见的问题总结. 1.Can not create instance of class: demo.DemoConfig. 觉得应该是你的路径有问题, 打开你项目的java build p ...
- java大全经典的书面采访
果学网 -专注IT在线www.prismcollege.com 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面.以便更充分地注意与当前目标有关的方面.抽象并 ...
- 简单ESB的服务架构
简单ESB的服务架构 这几个月一直在修改架构,所以迟迟没有更新博客. 新的架构是一个基于简单esb的服务架构,主要构成是esb服务注册,wcf服务,MVC项目构成. 首先,我门来看一看解决方案, 1. ...
- cocos2D(八)---- CCMenu && CCMenuItem
些菜单项让用户開始游戏.暂停\继续游戏.打开\关闭音乐或者是返回到上一个界面,比方以下两张图中用红色线框标记的菜单项 我们能够使用CCMenu和CCMenuItem实现上述的菜单功能,CCMe ...
- bzoj1001/BJOI2006 灰太狼抓到的兔子
1001: [BeiJing2006]狼抓兔子(id=1001">传送门) 图论新知识..没学过.. 平面图最小割等于对偶图的最短路 详见课件:http://wenku.baidu.c ...
- POJ1274 The Perfect Stall【二部图最大匹配】
主题链接: id=1274">http://poj.org/problem? id=1274 题目大意: 有N头奶牛(编号1~N)和M个牛棚(编号1~M). 每头牛仅仅可产一次奶.每一 ...
- Javascript中的__proto__、prototype、constructor
今天重温了下Javacript,给大家带来一篇Javascript博文,相信对于Javacript有一定了解的人都听过prototype原型这个概念,今天我们深度的分析下prototype与__pro ...
- 阿里游戏大数据sesson2_RF&GBRT(上)
----------一个小的游戏体验,对于不太熟悉Xlab RF和GBRT同学们都叫参考,不喜勿喷,大神绕道,米姆达. . .. .---------- 6月初的时候LR 做到4.9后一直上不去,看群 ...
- asp.net使用mysql数据库
Asp.net连接mysql 不推荐使用ODBC,推荐是用mysql官网提供的组件MySQL.Data.Dll,放在bin下面,添加引用即可 下面是封装的几个常用操作 using System; us ...