jQuery选择器源码解读(四):tokenize方法的Expr.preFilter_jquery
时间:2021-07-01 10:21:17
帮助过:9人阅读
Expr.preFilter是tokenize方法中对ATTR、CHILD、PSEUDO三种选择器进行预处理的方法。具体如下:
结果为2
*
* 等号右侧的“+”的作用是强制类型转换,将之后的字符串转换成数值类型
*/
match[4] = +(match[4] ? match[5] + (match[6] || 1)
: 2 * (match[3] === "even" || match[3] === "odd"));
match[5] = +((match[7] + match[8]) || match[3] === "odd");
} else if (match[3]) {
/*
* 若非nth起头的其它CHILD类型选择器带有括号说明,则抛出异常
* 这里jQuery并没有严格按照W3C的规则来判定,因为其允许:first-child()的这种形式存在
* 也就是对于jQuery来说:first-child()等同于:first-child,是合法选择器
*/
Sizzle.error(match[0]);
}
return match;
},
"PSEUDO" : function(match) {
/*
* 完成如下任务:
* 1、获取伪类中用引号括起来的值
* 2、对于非引号括起来的值,若存在伪类嵌套,则进一步解析确定当前伪类实际结束位置,
* 获取当前伪类的完整字符串和值
* 3、返回match中的前三项的副本。
*
* unquoted表示括号内非引号括起来的值,
* 以:eq(2)为例,unquoted=2
*/
var excess, unquoted = !match[5] && match[2];
/*
* 因为pseudo与child的匹配正则表达式有交集,所以,需要把属于child的部分忽略掉
*/
if (matchExpr["CHILD"].test(match[0])) {
return null;
}
/*
* 若括号内的值使用引号(match[3])括起来的,
* 则将除引号外的值(match[4])赋给match[2]。
* match[3]表示引号。
*/
if (match[3] && match[4] !== undefined) {
match[2] = match[4];
} else if (unquoted
/*
* rpseudo.test(unquoted):用来测试unquoted是否包含伪类,
* 若包含伪类,则说明有可能存在伪类嵌套的可能性,需要进一步对unquoted进行解析
* 例如: :not(:eq(3))
*/
&& rpseudo.test(unquoted)
&&
/*
* 获取unquoted中连续有效地选择器最后一个字符所在位置
*/
(excess = tokenize(unquoted, true))
&&
/*
* unquoted.indexOf(")", unquoted.length - excess)
* 从之前获得的连续有效地选择器最后一个字符所在位置之后找到")"所在位置,
* 通常就在当前位置之后。
* 再减去unquoted.length,用来获得match[0]中的有效完整的伪类字符串最后位置,
* 注意,此时excess是一个负值
*
*/
(excess = unquoted.indexOf(")", unquoted.length
- excess)
- unquoted.length)) {
// 获取有效的完整伪类match[0]和伪类括号内的数据match[2]
match[0] = match[0].slice(0, excess);
match[2] = unquoted.slice(0, excess);
}
// 返回match前三个元素的副本
return match.slice(0, 3);
}
}