$("form div > p[name=aaron]")解析的流程:
編譯器:分5個步驟
涉及: tag元素 關係選擇器 屬性選擇器
1:通過tokenize詞法分析器分組
2:遍歷tokens,從右邊往左邊開始篩選,最快定位到目標元素合集
//操作如下先看看有沒有搜尋器find,搜尋器就是瀏覽器一些原生的取dom介面,簡單的表述就是以下物件了
=
expr.find["tag"] = support.getelementsbytagname ?那麼第一篩選找到的定位元素,就形成了乙個 seed種子合集,那麼餘下的所有的操作都是圍繞這個種子合集處理function
( tag, context )
} :
因為節點總是存在各種關係的,所以不管是通過這個最靠近的目標的元素,往上還是往下 都是可以處理的
3:重組選擇器,開始執行繼續分解"form div > [name=aaron]"
因為種子合已經抽出了,所以選擇器就需要重新排列
"form div > [name=aaron]"踢掉了p元素,已經被抽離了
4 : 生成編譯處理器
這裡為什麼要這麼複雜,因為生成了編譯閉包可以快取起來,通過這種機制,增加了重複選擇器的效率
在matcherfromtokens方法中通過分解tokens生成對應的處理器
例如:form div [name=aaron]
在分解過程中分2大塊
a:關係選擇器的處理 > + ~ 空
b: attr child class id pseudo tag的處理
用matchers保留組合關係
1:分解第乙個tag:form 儲存處理器到matchers.push( expr.filter[「tag」]) ;
2:分解第二個「空」的關係選擇器,此時
a:用elementmatcher把之前的matchers壓入到這個匹配裡面,生成乙個遍歷方法的處理functionelementmatcher( matchers )
}return
true
; } :
matchers[0];
}
b:用addcombinator再次包裝,生成乙個位置關係的查詢關係所以此時的matchers的關係是乙個層級的包含結構,然後依次這樣遞迴functionaddcombinator( matcher, combinator, base ) );
if ( (oldcache = outercache[ dir ]) &&oldcache[ 0 ] === dirruns && oldcache[ 1 ] ===donename )
else}}
}};}
這個地方相當繞!!!!
生成的最後
cached = matcherfromtokens( match[i] );
變成了乙個超大的巢狀閉包
5: 通過matcherfromgroupmatchers這個函式來生成最終的匹配器
var byset = setmatchers.length > 0,通過matcherfromgroupmatchers的處理最直接的就是能看出,elementmatchers, setmatchers 2個結果不需要再返回出去,直接形成curry的方法,在內部就合併引數byelement = elementmatchers.length > 0,
supermatcher = function
(seed, context, xml, results, outermost)
return supermatcher
外面就直接呼叫了,這樣
var compilefunc = compiled ||compile( selector, match );compilefunc 一直是持有elementmatchers, setmatchers 的引用的,這個設計的手法還是值得借鑑的compilefunc(
seed,
context,
!documentishtml,
results,
outermost
);
執行期:
至此之前的5個步驟都是編譯成函式處理器的過程,然後就是開始執行了
粗的原理就是把直接分解出來的seed種子合集丟到這個處理器中,然後處理器就會根據各種關係進行分解匹配
從而得到結果集
supermatcher:
while ( (matcher = elementmatchers[j++]) )抽出第乙個seed元素,p}
然後把p丟到atrr是過濾篩選器中去匹配下,看看是否能找到對應的這個屬性
當然還是繼續從右往左邊匹配過濾了
一次是【name=aaron】 => div => from
matchers[i] => expr.filter.attr =>
p.getattribute(『name=aaron』) => 得到結果
function如果匹配失敗,自然就退出了 returnelementmatcher( matchers )
}return
true
; } :
matchers[0];
}
false ,就不需要在往前找了 ,然後再次遞迴seed
如果成功,就需要再深入的匹配了
因為是從右到左逐個匹配,所以往前走就會遇到關係選擇器的問題,
那麼jquery把四種關係 > + ~ 空的處理給抽出乙個具體的方法就是addcombinator
1 "form div > p[name=aaron]"
2 seed => p
3 篩選[name=aaron]
4 > => addcombinator方法 找到對應關係對映的父節點elem
5 elem中去匹配div 遞迴elementmatcher方法
6 「空」 => addcombinator方法找到祖先父節點elem
7 elem中去找form為止
可見這個查詢是及其複雜繁瑣的
總結:sizzle對選擇器的大概是思路:
分解所有的選擇器為最小單元,從右往左邊開始挑出乙個瀏覽器的api能快速定位的元素tag,id,class節點,這樣就能確定最終的元素跟這個元素是有關係的
然後把剩餘的選擇器單元開始生成乙個匹配器,主要是用來做篩選,最後根據關係分組
如果就依次匹配往上查詢,通過關係處理器定位上乙個節點的元素,通過普通匹配器去確定是否為可選的內容
sizzle分析記錄 分解流程
js form div p name aaron 解析的流程 編譯器 分5個步驟 涉及 tag元素 關係選擇器 屬性選擇器 1 通過tokenize詞法分析器分組 2 遍歷tokens,從右邊往左邊開始篩選,最快定位到目標元素合集 先看看有沒有搜尋器find,搜尋器就是瀏覽器一些原生的取dom介面,...
sizzle分析記錄 自定義偽類選擇器
可見性 隱藏物件沒有寬高,前提是用display none處理的 jquery.expr.filters.hidden function elem jquery.expr.filters.visible function elem 內容獲取文字內容通過indexof匹配 contains markf...
sizzle分析記錄 自定義偽類選擇器
可見性 隱藏物件沒有寬高,前提是用display none處理的 jquery.expr.filters.hidden function elem jquery.expr.filters.visible function elem 內容獲取文字內容通過indexof匹配 contains markf...