jQuery源码分析之sizzle选择器详解

2020-05-23 06:19:08易采站长站整理


jQuery.find = Sizzle;

function Sizzle(selector, context, results, seed) {
var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument,

// nodeType defaults to 9, since context defaults to document
nodeType = context ? context.nodeType : 9;

results = results || [];

// Return early from calls with invalid selector or context
if (typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {

return results;
}

// Try to shortcut find operations (as opposed to filters) in HTML documents
if (!seed) {

if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
// setDocument 函数其实是用来将 context 设置成 document,考虑到浏览器的兼容性
setDocument(context);
}
context = context || document;
// true
if (documentIsHTML) {

// match 就是那个有规律的数组
if (nodeType !== 11 && (match = rquickExpr.exec(selector))) {

// selector 是 id 的情况
if ((m = match[1])) {

// Document context
if (nodeType === 9) {
if ((elem = context.getElementById(m))) {

if (elem.id === m) {
results.push(elem);
return results;
}
} else {
return results;
}

// 非 document 的情况
} else {

if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) {

results.push(elem);
return results;
}
}

// selector 是 tagName 情况
} else if (match[2]) {
// 这里的 push:var push = arr.push
push.apply(results, context.getElementsByTagName(selector));
return results;

// selector 是 class 情况
} else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) {

push.apply(results, context.getElementsByClassName(m));
return results;
}
}

// 如果浏览器支持 querySelectorAll
if (support.qsa && !compilerCache[selector + " "] && (!rbuggyQSA || !rbuggyQSA.test(selector))) {

if (nodeType !== 1) {
newContext = context;
newSelector = selector;

// qSA looks outside Element context, which is not what we want
// Support: IE <=8,还是要考虑兼容性
} else if (context.nodeName.toLowerCase() !== "object") {

// Capture the context ID, setting it first if necessary
if ((nid = context.getAttribute("id"))) {
nid = nid.replace(rcssescape, fcssescape);
} else {
context.setAttribute("id", (nid = expando));
}

// Sizzle 词法分析的部分
groups = tokenize(selector);
i = groups.length;
while (i--) {
groups[i] = "#" + nid + " " + toSelector(groups[i]);