jQuery技术内幕:深入解析jQuery架构设计与实现原理. 3.7 Sizzle.filter( expr, set, inplace, not )

3.7 Sizzle.filter( expr,
set, inplace, not )

方法Sizzle.filter( expr, set, inplace, not )负责用块表达式过滤元素集合。在该方法内部,将用过滤函数集Sizzle.selectors.filter中的过滤函数来执行过滤操作。

方法Sizzle.filter( expr, set, inplace, not )实现的5个关键步骤如下:

1)首先用正则集合Sizzle.selectors.leftMatch中的正则确定块表达式类型。

2)然后调用预过滤函数集Sizzle.selectors.preFilter中对应类型的预过滤函数,执行过滤前的修正操作。

3)调用过滤函数集Sizzle.selectors.filter[
type ]中对应类型的过滤函数,执行过滤操作,如果过滤函数返回false,则把元素集合中对应位置的元素替换为false。

4)最后删除块表达式中已过滤的部分。

5)重复第1)~4)步,直至块表达式变为空字符串。

下面来看看该方法的源码实现。

1.定义Sizzle.filter(
expr, set, inplace, not )

相关代码如下所示:

4086 Sizzle.filter = function( expr, set,
inplace, not ) {

第4086行:定义方法Sizzle.filter( expr, set, inplace, not ),它接受 4 个参数:

参数expr:块表达式。

参数set:待过滤的元素集合。

参数inplace:布尔值。如果为true,则将元素集合set中与选择器表达式不匹配的元素设置为false;如果不为true,则重新构造一个元素数组并返回,只保留匹配元素。

参数not:布尔值。如果为true,则去除匹配元素,保留不匹配元素;如果不为true,则去除不匹配元素,保留匹配元素。

2.?用块表达式expr过滤元素集合set,直到expr为空

相关代码如下所示:

4087    
var match, anyFound,

4088        
type, found, item, filter, left,

4089        
i, pass,

4090        
old = expr,

4091        
result = [],

4092        
curLoop = set,

4093        
isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );

4094

4095    
while ( expr && set.length ) {

第4095行:用块表达式expr过滤元素集合set,直到expr变为空字符串。如果候选集set变为空数组,则没有必要继续执行过滤操作。

(1)遍历块过滤函数集Sizzle.selectors.filter

相关代码如下所示:

4096        
for ( type in Expr.filter ) {

第4096行:遍历块过滤函数集Sizzle.selectors.filter,调用其中的过滤函数执行过滤操作。块过滤函数集Sizzle.selectors.filter中定义了PSEUDO、CHILD、ID、TAG、CLASS、ATTR、POS对应的过滤函数,具体请参见3.9.7节。

(2)确定块表达式类型Sizzle.selectors.leftMatch[ type ]

相关代码如下所示:

4097             if ( (match = Expr.leftMatch[ type
].exec( expr )) != null && match[2] ) {

4098                 filter = Expr.filter[ type ];

4099                 left = match[1];

4100

4101                 anyFound = false;

4102

4103                 match.splice(1,1);

4104

4105                 if ( left.substr( left.length
- 1 ) === "\\" ) {

4106                     continue;

4107                 }

4108

第4097行:检查每个表达式类型type在Sizzle.selectors.leftMatch中对应的正则是否匹配块表达式expr,如果匹配,则可以确定块表达式的类型。

第4105~4107行:如果匹配正则的内容以反斜杠"\\"开头,表示反斜杠"\\"之后的字符被转义了,不是期望的类型,这时会认为类型匹配失败。

(3)调用预过滤函数Sizzle.selectors.preFilter[ type ]

相关代码如下所示:

4109                 if ( curLoop === result ) {

4110                     result = [];

4111                 }

4112

4113                 if ( Expr.preFilter[ type ] )
{

4114                     match = Expr.preFilter[
type ]( match, curLoop, inplace, result, not, isXMLFilter );

4115

4116                     if ( !match ) {

4117                        anyFound = found =
true;

4118

4119                     } else if ( match === true
) {

4120                        continue;

4121                     }

4122                 }

4123

第4109~4111行:用于缩小候选集。

第4113~4122行:如果在预过滤函数集Sizzle.selectors.preFilter中存在对应的预过滤函数,则调用,执行过滤前的修正操作。预过滤函数负责进一步修正过滤参数,具体请参见3.9.4节。

第4116~4121行:预过滤函数有3种返回值:

false:已经执行了过滤,缩小了候选集,例如,CLASS。

true:需要继续执行预过滤,尚不到执行过滤函数的时候,例如,POS、CHILD。

字符串:修正后的过滤参数(通常是块表达式),后面会继续调用对应的过滤函数。

(4)调用过滤函数Sizzle.selectors.filter[ type ]

相关代码如下所示:

4124                 if ( match ) {

4125                     for ( i = 0; (item =
curLoop[i]) != null; i++ ) {

4126                         if ( item ) {

4127                             found = filter(
item, match, i, curLoop );

4128                             pass = not ^
found;

4129

4130                             if ( inplace
&& found != null ) {

4131  
                              if (
pass ) {

4132                                     anyFound =
true;

4133

4134                                 } else {

4135                                     curLoop[i]
= false;

4136                                 }

4137

4138                             } else if ( pass )
{

4139                                 result.push(
item );

4140                                 anyFound =
true;

4141                             }

4142                         }

4143                     }

4144                 }

4145

第4124~4144行:遍历元素集合curLoop,对其中的每个元素执行过滤函数,检测元素是否匹配。

第4127~4128行:变量found表示当前元素是否匹配过滤表达式;变量pass表示当前元素item是否可以通过过滤表达式的过滤。如果变量found为true,表示匹配,此时如果未指定参数not,则变量pass为true;如果变量found为false,表示不匹配,此时如果参数not为true,则变量pass为true;其他情况下,变量pass为false。

第4130~4141行:如果参数inplace为true,则将与块表达式expr不匹配的元素设置为false;如果参数inplace不是true,则重新构造一个元素数组,只保留匹配元素,即会不断地缩小元素集合。

(5)删除块表达式expr中已过滤的部分

相关代码如下所示:

4146                 if ( found !== undefined ) {

4147                     if ( !inplace ) {

4148       
                 curLoop = result;

4149                     }

4150

4151                     expr = expr.replace(
Expr.match[ type ], "" );

4152

4153                     if ( !anyFound ) {

4154                         return [];

4155                     }

4156

4157                     break;

4158                 }

4159             }

4160        
}

4161

第4146行:变量found是过滤函数Sizzle.selectors.filter[ type ]的返回值,如果不等于undefined,表示至少执行过一次过滤。大多数情况下,过滤操作发生在过滤函数中,不过也可能发生在预过滤函数中,例如,CLASS、POS、CHILD。

第4147~4149行:如果参数inplace不是true,则将新构建的元素数组赋值给变量curLoop,在下次循环时,会将result再次置为空数组(见第4109~4111行),然后存放通过过滤的元素(见第4130~4141行),然后再赋值给变量curLoop,即会不断地缩小元素集合。

第4151行:删除块表达式中已过滤过的部分,直至块表达式变为空字符串。用对象Sizzle.selectors.match中对应的正则匹配已过滤过的部分,具体请参见3.9.2节。

第4153~4155行:如果没有找到可以通过过滤的元素,直接返回一个空数组。

(6)如果块表达式没有发生变化,则认为不合法

相关代码如下所示:

4162        
// Improper expression

4163        
if ( expr === old ) {

4164             if ( anyFound == null ) {

4165                 Sizzle.error( expr );

4166

4167             } else {

4168                 break;

4169             }

4170        
}

4171

4172        
old = expr;

4173    
}

4174

 

4178 Sizzle.error = function( msg ) {

4179    
throw new Error( "Syntax error, unrecognized expression: " +
msg );

4180 };

第4163~4172行:如果块表达式expr没有发生变化,说明前面的过滤没有生效,动不了块表达式expr分毫,此时如果没有找到可以通过过滤的元素,则认为块表达式expr不合法,抛出语法错误的异常。

3.?返回过滤后的元素集合,或缩减范围后的元素集合

相关代码如下所示:

4175    
return curLoop;

4176 };

方法Sizzle.filter( expr, set, inplace, not )的执行过程可以总结为图3-6。

时间: 2024-11-05 14:54:42

jQuery技术内幕:深入解析jQuery架构设计与实现原理. 3.7 Sizzle.filter( expr, set, inplace, not )的相关文章

jQuery技术内幕:深入解析jQuery架构设计与实现原理1

jQuery技术内幕:深入解析jQuery架构设计与实现原理 高 云 著 图书在版编目(CIP)数据 jQuery技术内幕:深入解析jQuery架构设计与实现原理 / 高云著. -北京:机械工业出版社,2013.11 ISBN 978-7-111-44082-6 I. j- II. 高- III. JAVA语言-程序设计 IV. TP312 中国版本图书馆CIP数据核字(2013)第221662号 版权所有·侵权必究 封底无防伪标均为盗版 本书法律顾问 北京市展达律师事务所     本书由阿里巴

jQuery技术内幕:深入解析jQuery架构设计与实现原理. 导读

   本书由阿里巴巴资深前端开发工程师撰写,从源代码角度全面而系统地解读了jQuery的17个模块的架构设计理念和内部实现原理,旨在帮助读者参透jQuery中的实现技巧和技术精髓,同时本书也对广大开发者如何通过阅读源代码来提升编码能力和软件架构能力提供了指导.     本书首先通过"总体架构"梳理了各个模块的分类.功能和依赖关系,让大家对jQuery的工作原理有大致的印象:进而通过"构造jQuery对象"章节分析了构造函数jQuery()的各种用法和内部构造过程:接

jQuery技术内幕:深入解析jQuery架构设计与实现原理2

第三部分 底层支持模块 第3章 选择器Sizzle 第4章 异步队列Deferred Object 第5章 数据缓存Data  第6章 队列Queue 第7章 浏览器功能测试Support 第3章 选择器Sizzle Sizzle是一款纯JavaScript实现的CSS选择器引擎,它具有以下特性: 完全独立,无库依赖. 相较于大多数常用选择器其性能非常有竞争力. 压缩和开启gzip后只有4?KB. 具有高扩展性和易于使用的API. 支持多种浏览器,如IE 6.0+.Firefox 3.0+.Ch

jQuery技术内幕:深入解析jQuery架构设计与实现原理. 3.9 Sizzle.selectors

3.9 Sizzle.selectors 对象Sizzle.selectors包含了Sizzle在查找和过滤过程中用到的正则.查找函数.过滤函数,其中包含的属性见图3-1,源码结构见代码清单3-1. 3.9.1 Sizzle.selectors.order 表达式类型数组Sizzle.selectors.order中定义了查找单个块表达式时的查找顺序,依次是ID.CLASS.NAME.TAG.其中,CLASS需要浏览器支持方法getElementsByClass Name().查找顺序综合考虑了

jQuery技术内幕:深入解析jQuery架构设计与实现原理. 3.4 Sizzle( selector, context, results, seed )

3.4 Sizzle( selector, context, results, seed ) 函数Sizzle( selector, context, results, seed )用于查找与选择器表达式selector匹配的元素集合.该函数是选择器引擎的入口. 函数Sizzle( selector, context, results, seed )执行的6个关键步骤如下: 1)解析块表达式和块间关系符. 2)如果存在位置伪类,则从左向右查找: a.?查找第一个块表达式匹配的元素集合,得到第一个

jQuery技术内幕:深入解析jQuery架构设计与实现原理. 3.13 总结

3.13 总结 在本章中,对选择器引擎Sizzle做了完整的介绍和分析,总体源码结构见代码清单3-1,方法功能和调用关系见图3-1.在本章的最后还介绍和分析了jQuery对Sizzle的整合和扩展. 选择器表达式由块表达式和块间关系符组成.块表达式分为3种:简单表达式.属性表达式.伪类表达式:块间关系符分为4种:">"父子关系.""祖先后代关系."+"紧挨着的兄弟元素."-"之后的所有兄弟元素:块表达式和块间关系符组成了

jQuery技术内幕:深入解析jQuery架构设计与实现原理. 3.3 设计思路

3.3 设计思路 在正式开始分析Sizzle的源码实现之前,先来讨论和分析下如果要执行一段选择器表达式,或者说设计一个简化版的选择器引擎,需要做些什么工作.下面以"div.red>p"为例来模拟执行过程,具体来说有从左向右查找和从右向左查找两种思路: 1)从左向右:先查找"div.red"匹配的元素集合,然后查找匹配"p"的子元素集合. 2)从右向左:先查找"p"匹配的元素集合,然后检查其中每个元素的父元素是否匹配&qu

基于微服务和Docker容器技术的PaaS云平台架构设计

本文讲的是基于微服务和Docker容器技术的PaaS云平台架构设计[编者的话]在系统架构上,PaaS云平台主要分为微服务架构.Docker容器技术.DveOps三部分,这篇文章重点介绍微服务架构的实施. [3 天烧脑式容器存储网络训练营 | 深圳站]本次培训以容器存储和网络为主题,包括:Docker Plugin.Docker storage driver.Docker Volume Pulgin.Kubernetes Storage机制.容器网络实现原理和模型.Docker网络实现.网络插件.

基于云技术的ELC集群式服务器架构设计与实现

基于云技术的ELC集群式服务器架构设计与实现 西安电子科技大学 张文 本文提出了一种基于云技术的弹性负载均衡集群式服务器架构(Elastic and Load Balancing Cluster Server Architecture based on CloudTechnology,ELC集群式服务器架构).本架构以Eucalyptus云计算平台为基础设施,按照计算与存储分离原则整体分为两部分.其中,计算服务系统在Eucalyptus云平台的计算模块基础上,通过虚拟服务器实例方式对外提供服务,