function Sizzle( selector, context, results, seed )
{
var match,
elem, m, nodeType,
// QSA vars
i, groups, old, nid, newContext, newSelector;
if (
( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
setDocument( context );
}
//上下文为传入context或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
);
}