JQuery_2.1.0_日记 5.5 Sizzle选择器(三)

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 );
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章