以下分析基于jQuery-1.10.2.js版本。
下面将以$("div:not(.class:contain('span')):eq(3)")为例,说明tokenize和preFilter各段代码是如何协调完成解析的。若想了解tokenize方法和preFilter类的每行代码的详细解释,请参看如下两篇文章:
//www.Vevb.com/article/63155.htm
//www.Vevb.com/article/63163.htm
下面是tokenize方法的源码,为了简便期间,我把有关缓存、逗号的匹配以及关系符的匹配的代码全部去掉了,只留了与当前例子有关的核心代码。被去掉的代码很简单,若需要可以看一下上述文章即可。
另外,代码统一写在说明文字上方。
代码如下:
function tokenize(selector, parseOnly) {
var matched, match, tokens, type, soFar, groups, preFilters;
soFar = selector;
groups = [];
preFilters = Expr.preFilter;
while (soFar) {
if (!matched) {
groups.push(tokens = []);
}
matched = false;
for (type in Expr.filter) {
if ((match = matchExpr[type].exec(soFar))
&& (!preFilters[type] || (match = preFilters[type]
(match)))) {
matched = match.shift();
tokens.push({
value : matched,
type : type,
matches : match
});
soFar = soFar.slice(matched.length);
}
}
if (!matched) {
break;
}
}
return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) :
tokenCache(selector, groups).slice(0);
}
首先,jQuery执行过程中由select方法首次调用tokenize,并将"div:not(.class:contain('span')):eq(3)"作为selector参数传入该方法。
代码如下:
soFar = selector;
soFar = "div:not(.class:contain('span')):eq(3)"
第一次进入while循环时,由于matched还未被赋值,所以执行if内的如下语句体,该语句将初始化tokens变量,同时,将tokens压入groups数组。
代码如下:
groups.push(tokens = []);
之后,进入for语句。
第一次for循环:从Expr.filter中取出第一个元素"TAG"赋给type变量,执行循环体代码。
代码如下:
if ((match = matchExpr[type].exec(soFar))
&& (!preFilters[type] || (match = preFilters[type]
(match)))) {
match = matchExpr[type].exec(soFar)的执行结果如下:
match =["div", "div"]
示例的第一个选择器为div,匹配matchExpr["TAG"]的正则表达式,且不存在preFilters["TAG"],故执行if内语句体。
新闻热点
疑难解答
图片精选