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视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ... 
随机推荐
- Xamarin:制作并发布apk
			原文:Xamarin:制作并发布apk 终于到了激动人心的时刻:要向真机发布apk了.流程如下: 1 制作release版的android应用安装包apk文件: 1.1 用VS2012中文版制作:记得 ... 
- 用户手册User Guide的写法
			下面的内容仅代表个人观点,是在工作中总结出来的,如果有错误之处,还请指教. 转载请注明来自博客园---”邦邦酱好“: http://www.cnblogs.com/bangbangjiang/p/36 ... 
- Type mismatch: cannot convert from Enumeration<String> to Enumeration<Object>
			完整的错误信息: Description Resource Path Location TypeType mismatch: cannot convert from Enumeration<St ... 
- 产品经理(五岁以下儿童)myVegas Slots排名上升的秘密
			myVEGAS Slots于AppStore上排名在今年也就是2月份时候飙升,那么什么情况导致这个现象的呢,我们试图通过App Annie的分析给出答案. 上面是myVegas的排名情况,我们能够看到 ... 
- ffmpeg架构和解码流程分析
			转 一,ffmpeg架构 1. 简介 FFmpeg是一个集录制.转换.音/视频编码解码功能为一体的完整的开源解决方案.FFmpeg的 开发是基于Linux操作系统,但是可以在大多数操作系统中编译和使用 ... 
- Zookeeper实践方案:(4)命名服务
			1.基本介绍 命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息.利用Zookeeper非常easy创建一个全局的路径,而这个路径就能够作为一个名字.它能够指向集群中的集群.提供的服务的 ... 
- android-sdk-windows下载版
			Android SDK 4.0.3 开发和执行环境配置 近期又装了一次最新版本号的ADK环境 眼下最新版是Android SDK 4.0.3 本文的插图和文本尽管是Android2.2的 步骤都是一样 ... 
- 移动web:转盘抽奖(幸运大转盘)
			为了获取客户.回馈客户,平台一般会推出抽奖活动类的营销页.因此web页面中,有各式各样的抽奖效果. 格子式(九宫格),背景滚动式(数字/文字/图案),旋转式(转盘),游戏式(砸蛋/拼图...).... ... 
- 在C#环境中动态调用IronPython脚本(一)
			本文讲述用C#调用Ironpython运行环境,解析并运行动态pyhton脚本.这种情况应用在那些需要滞后规定行为的场合,例如,动态计算项(计算引擎),用户可以自定义计算内容.计算公式等. 本文的代码 ... 
- WCF 部署时,soap:address location 显示的是电脑名,而不是ip地址
			部署WCF服务时,发现soap:address location 和wsdl:import location 显示是电脑名,而不是ip地址,这样外面公司的人就无法下载剩下的wsdl,post也会往错误 ... 
