jQuery原始碼研究:選擇器
阿新 • • 發佈:2019-01-11
jQuery
的css選擇器,是一大亮點,其實現原始碼也可單獨拎出來作為模組使用。
先看個整體,在jQuery
原始碼中在行229-2752區域。
var Sizzle = (function(window){
// 具體實現暫略...
})(window)
css選擇器的具體實現是一個匿名自執行函式,傳入引數為window
物件。函式頂部定義若干變數,包括本地文件變數、特定例項資料和特定例項方法,此外還定義了一些為選擇器字串服務的正則表示式。數量太多就不一一列舉了,感興趣的可以自己去看原始碼吧。
方法的主體從行715開始直到結束,定義了Sizzle
建構函式,若干工具方法和Sizeele
圖1
1、Sizzle
建構函式:
function Sizzle( selector, context, results, seed ){
var m, i, elem, nid, match, groups, newSelector,
newContext = context && context.ownerDocument,
//上下文預設為document,節點型別預設為9
nodeType = context ? context.nodeType : 9;
results = results || [];
// 對選擇器值為非字串、為假、節點型別不符合要求時的返回值進行處理
if ( typeof selector !== "string" || !selector ||
nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
return results;
}
// 操作HTML文件
if ( !seed ) {
if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
setDocument( context );
}
context = context || document;
if ( documentIsHTML ) {
if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
// ID 選擇器
if ( (m = match[1]) ) {
// 文件內容
if ( nodeType === 9 ) {
if ( (elem = context.getElementById( m )) ) {
if ( elem.id === m ) {
results.push( elem );
return results;
}
} else {
return results;
}
// 元素內容
} else {
if ( newContext && (elem = newContext.getElementById( m )) &&
contains( context, elem ) &&
elem.id === m ) {
results.push( elem );
return results;
}
}
// 型別選擇器
} else if ( match[2] ) {
push.apply( results, context.getElementsByTagName( selector ) );
return results;
// Class 選擇器
} else if ( (m = match[3]) && support.getElementsByClassName &&
context.getElementsByClassName ) {
push.apply( results, context.getElementsByClassName( m ) );
return results;
}
}
if ( support.qsa &&
!compilerCache[ selector + " " ] &&
(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
if ( nodeType !== 1 ) {
newContext = context;
newSelector = selector;
} else if ( context.nodeName.toLowerCase() !== "object" ) {
if ( (nid = context.getAttribute( "id" )) ) {
nid = nid.replace( rcssescape, fcssescape );
} else {
context.setAttribute( "id", (nid = expando) );
}
groups = tokenize( selector );
i = groups.length;
while ( i-- ) {
groups[i] = "#" + nid + " " + toSelector( groups[i] );
}
newSelector = groups.join( "," );
newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
context;
}
if ( newSelector ) {
try {
push.apply( results,
newContext.querySelectorAll( newSelector )
);
return results;
} catch ( qsaError ) {
} finally {
if ( nid === expando ) {
context.removeAttribute( "id" );
}
}
}
}
}
}
// 返回 呼叫select()方法後的值
return select( selector.replace( rtrim, "$1" ), context, results, seed );
}
Sizzle
函式是整個css選擇器的入口函式。
喜歡本文請掃下方二維碼,關注微信公眾號: 前端小二,檢視更多我寫的文章哦,多謝支援。