jQuery选择器正则表达式是jQuery选择器框架Sizzle的基础。Sizzle正则表达式集中在Expr对象的match对象属性中,这里定义的RE是基础的、按照功能分类的。另一个核心RE是变量chunker定义的。
分析这些RE的思路:一是按顺序找出所有的分组(程序解析过程与分组紧密相关),二是清晰其结构。分组用颜色表示(这里用了两种颜色以区分位置上连续的但逻辑上不连续的分组),结构区分用换行。





对match的统一处理逻辑是:在正则表达式前面(右方)追加一个验证当前正则表达式正确性的反前向锚,即当前正则表达式的前方不能出现一个未经匹配的孤立的右方括号或者右圆括号。
在此基础上,在正则表达式后面(左方)追加一个同样是验证作用的捕获分组,这时问题来了,在正则表达式前面(右方)追加锚时不涉及到分组,不会对已存在的正则表达式对象产生影响(即使追加的是分组也不会影响已存在的正则表达式),但是在正则表达式后面(左方)追加分组时会影响已存在的正则表达式对象--原分组数字后向引用如果不依次递增将会引用错误的分组,此时不得不修正改动已存在的正则表达式对象(主要是分组引用数字值增一),这就是fescape函数在replace方法中的作用。经过前后增强的正则表达式对象存入Expr的leftMatch对象中,后面我们会看到,Sizzle实际使用的是增强的match对象和leftMatch对象。

一 Expr对象的正则表达式
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\))?/
}分析这些RE的思路:一是按顺序找出所有的分组(程序解析过程与分组紧密相关),二是清晰其结构。分组用颜色表示(这里用了两种颜色以区分位置上连续的但逻辑上不连续的分组),结构区分用换行。
这样定义的Sizzle的所有正则表达式从功能上来讲差不多是够了,但是从健壮性的角度来讲还远远不够,毕竟一套健壮的机器不能仅仅期望用户严格按照操作说明文档来输入或操作,在用户非常规的甚至错误的输入数据或操作时依然能正确运转的才是成熟的产品,为此Sizzle对match正则对象做了统一处理并给出了一套增强版的leftMatch对象。
var origPOS = Expr.match.POS,
fescape = function(all, num){
return "\\" + (num - 0 + 1);
};
for ( var type in Expr.match ) {
Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}对match的统一处理逻辑是:在正则表达式前面(右方)追加一个验证当前正则表达式正确性的反前向锚,即当前正则表达式的前方不能出现一个未经匹配的孤立的右方括号或者右圆括号。
在此基础上,在正则表达式后面(左方)追加一个同样是验证作用的捕获分组,这时问题来了,在正则表达式前面(右方)追加锚时不涉及到分组,不会对已存在的正则表达式对象产生影响(即使追加的是分组也不会影响已存在的正则表达式),但是在正则表达式后面(左方)追加分组时会影响已存在的正则表达式对象--原分组数字后向引用如果不依次递增将会引用错误的分组,此时不得不修正改动已存在的正则表达式对象(主要是分组引用数字值增一),这就是fescape函数在replace方法中的作用。经过前后增强的正则表达式对象存入Expr的leftMatch对象中,后面我们会看到,Sizzle实际使用的是增强的match对象和leftMatch对象。
二 chunker变量
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g
本文探讨了jQuery中的Sizzle选择器系统,尤其是Expr对象的正则表达式部分。尽管现有的正则表达式基本满足功能需求,但为了提高健壮性,Sizzle通过统一处理match正则对象并创建增强的leftMatch对象,以应对不规范或错误的用户输入,确保选择器在各种情况下都能正确工作。
6826

被折叠的 条评论
为什么被折叠?



