function Sizzle( selector, context, results, seed ) { var match, elem, m, nodeType, // QSA vars i, groups, old, nid, newContext, newSelector; //注意这个document只是个普通的变量 //setDocument()方法根据当前运行代码的环境,设置当前的document //传入的context的doucument和当前document不一样时 //调用setDocument() //用于在 frame 中的情况 //context为document时,context.ownerDocument为null if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { //设置正确的document setDocument( context ); } //上下文为传入context或调用setDocument()后的document context = context || document; //查询结果集 results = results || []; //如果没传入选择器表达式或者传入的选择器表达器类型不是string if ( !selector || typeof selector !== "string" ) { //返回 return results; } //如果上下文不是Element或Document //返回空结果集 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { return []; } //文档是HTML并且没有传入候选集seed if ( documentIsHTML && !seed ) { // Shortcuts // 快速匹配最常用的单一id tag class //rquickExpr 捕获组1:id 捕获组2:tag 捕获组3:class if ( (match = rquickExpr.exec( selector )) ) { // Speed-up: Sizzle("#ID") //id 分支 if ( (m = match[1]) ) { //context是document if ( nodeType === 9 ) { elem = context.getElementById( m ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document (jQuery #6963) if ( elem && elem.parentNode ) { // Handle the case where IE, Opera, and Webkit return items // by name instead of ID //看上面注释! if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } } else { // Context is not a document //得到上下文所属document,然后调用document.getElementById,并判断得到的elem是否属于contains并且看看elem的id属性是否等于m if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Speed-up: Sizzle("TAG") // tag分支 } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Speed-up: Sizzle(".CLASS") // class分支 } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // QSA path // 支持querySelectorAll,rbuggyQSA怪癖检查 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { nid = old = expando; newContext = context; //newSelector的值为false或selector //如果nodeType !== 9 返回false,其他返回selector newSelector = nodeType === 9 && selector; // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements //如果调通querySelectorAll的是Element会出现一些怪异的问题 //所以在原selector的基础上方添加一个id的属性选择器 //例如媛selector:div a,修正后为[id='xx'] div a if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { groups = tokenize( selector ); //如果Element元素有id,则使用原来id if ( (old = context.getAttribute("id")) ) { //rescape = /'|\\/g nid = old.replace( rescape, "\\$&" ); //没有id设置一个临时id,此id是expando属性 } else { context.setAttribute( "id", nid ); } nid = "[id='" + nid + "'] "; i = groups.length; while ( i-- ) { groups[i] = nid + toSelector( groups[i] ); } newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; newSelector = groups.join(","); } //修正newSelector,调用querySelectorAll if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch(qsaError) { } finally { //如果用的时临时id //删除 if ( !old ) { context.removeAttribute("id"); } } } } } // All others //原生方法不可用时,调用 return select( selector.replace( rtrim, "$1" ), context, results, seed ); }