function select(selector, context, results, seed) {
var i, tokens, token, type, find,
// 调用tokenize函数解析selector
match = tokenize(selector);
// 若没有提供初始集合
if (!seed) {
// Try to minimize operations if there is only one group
// 若只有一组选择器,即选择器字符串没有逗号
if (match.length === 1) {
// Take a shortcut and set the context if the root selector
// is an ID
tokens = match[0] = match[0].slice(0);
if (tokens.length > 2 && (token = tokens[0]).type === "ID"
&& support.getById && context.nodeType === 9
&& documentIsHTML && Expr.relative[tokens[1].type]) {
// 将当前上下文指向第一个ID选择器指定的节点对象
context = (Expr.find["ID"](token.matches[0].replace(
runescape, funescape), context) || [])[0];
// 若当前上下文内没有指定ID对象,则直接返回results
if (!context) {
return results;
}
// 选择器字符串去掉第一个ID选择器
selector = selector.slice(tokens.shift().value.length);
}
// Fetch a seed set for right-to-left matching
i = matchExpr["needsContext"].test(selector) ? 0
: tokens.length;
while (i--) {
token = tokens[i];
// Abort if we hit a combinator
// 遇到关系符跳出循环
if (Expr.relative[(type = token.type)]) {
break;
}
if ((find = Expr.find[type])) {
// Search, expanding context for leading sibling
// combinators
if ((seed = find(token.matches[0].replace(
runescape, funescape), rsibling
.test(tokens[0].type)
&& context.parentNode || context))) {
// If seed is empty or no tokens remain, we can
// return early
// 剔除刚用过的选择器
tokens.splice(i, 1);
selector = seed.length && toSelector(tokens);
if (!selector) {
push.apply(results, seed);
return results;
}
break;
}
}
}
}
}
// Compile and execute a filtering function
// Provide `match` to avoid retokenization if we modified the
// selector above
compile(selector, match)(seed, context, !documentIsHTML, results,
rsibling.test(selector));
return results;
}