<b>3.6 sizzle.find( expr,</b>
context, isxml )
方法sizzle.find( expr, context, isxml )負責查找與塊表達式比對的元素集合。該方法會按照表達式類型數組sizzle.selectors.order規定的查找順序(id、class、name、tag)逐個嘗試查找,如果未找到,則查找上下文的所有後代元素(*)。
圖3-3 sizzle( selector, context, results, seed )的執行過程
方法sizzle.find( expr, context, isxml )執行的5個關鍵步驟如下:
1)先用正則集合sizzle.selectors.leftmatch中的正則确定表達式類型。
2)然後調用查找函數集sizzle.selectors.find中對應類型的查找函數,查找比對的元素集合。
3)然後删除塊表達式中已查找過的部分。
4)如果沒有找到對應類型的查找函數,則讀取上下文的所有後代元素。
5)最後傳回格式為{set:候選集, expr:塊表達式剩餘部分}的對象。
下面來看看該方法的源碼實作。
1.?定義sizzle.find( expr,
相關代碼如下所示:
4051 sizzle.find = function( expr, context,
isxml ) {
第4051行:定義方法sizzle.find( expr, context, isxml ),它接受3個參數:
參數expr:塊表達式。
參數context:dom元素或文檔對象,作為查找時的上下文。
參數isxml:布爾值,訓示是否運作在一個xml文檔中。
2.?周遊表達式類型數組sizzle.selectors.order
4052
var set, i, len, match, type, left;
4053
4054
if ( !expr ) {
4055
return [];
4056
}
4057
4058
for ( i = 0, len = expr.order.length; i < len; i++ ) {
4059
type = expr.order[i];
4060
第4054~4056行:如果塊表達式expr是空字元串,則直接傳回空數組[]。
第4058行:表達式類型數組sizzle.selectors.order中定義了查找單個塊表達式時的順序,依次是id、class、name、tag,其中,class需要浏覽器支援方法getelements
byclassname()。關于sizzle.selectors.order的具體說明請參見3.9.1節。
(1)确定塊表達式類型sizzle.selectors.leftmatch[ type ]
4061
if ( (match = expr.leftmatch[ type ].exec( expr )) ) {
4062 left = match[1];
4063 match.splice( 1, 1 );
4064
第4061行:檢查每個表達式類型type在sizzle.selectors.leftmatch中對應的正則是否比對塊表達式expr,如果比對,則可以确定塊表達式的類型。
第4062~4063行:對象sizzle.selectors.leftmatch中存放了表達式類型和正則的映射,正則可以用于确定塊表達式的類型,并解析其中的參數。它是基于對象sizzle.selectors.match初始化的,具體請參見3.9.2節。
(2)查找比對元素sizzle.selectors.find[ type ]
4065 if ( left.substr( left.length - 1
) !== "\\" ) {
4066 match[1] = (match[1] ||
"").replace( rbackslash, "" );
4067 set = expr.find[ type ](
match, context, isxml );
4068
第4065行:如果比對正則的内容以反斜杠"\\"開頭,表示反斜杠"\\"之後的字元被轉義了,不是期望的類型,這時會認為類型比對失敗。
第4066行:過濾其中的反斜杠,以支援将某些特殊字元(例如,“#”、“.”、“[”)作為普通字元使用。舉個例子,假設某個input元素的屬性id是"a.b",則對應的選擇器表達式應該寫作$("#a\\.b"),這裡替換掉了反斜杠,又會變回"a.b",是以仍然可以通過執行document.getelementsbyid("a.b")查找到input元素。
第4067行:調用表達式類型type在查找函數集sizzle.selectors.find中對應的查找函數,查找比對的元素集合。sizzle.selectors.find中定義了id、class、name、tag所對應的查找函數,具體請參見3.9.3節。
(3)删除塊表達式中已查找過的部分
4069 if ( set != null ) {
4070 expr = expr.replace(
expr.match[ type ], "" );
4071 break;
4072 }
4073 }
4074
4075
4076
第4069~4072行:如果set不是null和undefined,表示對應的查找函數執行了查找操作,則不管有沒有找到比對元素,都将塊表達式expr中已查找過的部分删除,并結束方法sizzle.find( expr, context, isxml )的查找過程。
第4070行:用對象sizzle.selectors.match中對應的正則來比對已查找過的部分,具體請參見3.9.2節。
3.?如果沒有找到對應類型的查找函數,則讀取上下文的所有後代元素
4077
if ( !set ) {
4078
set = typeof context.getelementsbytagname !== "undefined" ?
4079 context.getelementsbytagname(
"*" ) :
4080 [];
4081
4082
第4077~4081行:如果set是null或undefined,(大多數情況下)表示沒有在sizzle.selectors.find中找到對應的查找函數,例如,$(":input")會讀取上下文的所有後代元素作為候選集。
4.?傳回{ set:候選集, expr:塊表達式剩餘部分}
4083
return { set: set, expr: expr };
4084 };
方法sizzle.find( expr, context, isxml )的執行過程可總結為圖3-5。
圖3-5 sizzle.find( expr, context, isxml )的執行過程