<a></a>
js
解析的流程:
編譯器:分5個步驟
涉及: TAG元素 關系選擇器 屬性選擇器
1:通過tokenize詞法分析器分組
2:周遊tokens,從右邊往左邊開始篩選,最快定位到目标元素合集
操作如下
那麼第一篩選找到的定位元素,就形成了一個 seed種子合集,那麼餘下的所有的操作都是圍繞這個種子合集處理
因為節點總是存在各種關系的,是以不管是通過這個最靠近的目标的元素,往上還是往下 都是可以處理的
3:重組選擇器,開始執行繼續分解"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壓入到這個比對裡面,生成一個周遊方法的處理
B:用addCombinator再次包裝,生成一個位置關系的查找關系
是以此時的matchers的關系是一個層級的包含結構,然後依次這樣遞歸
這個地方相當繞!!!!
生成的最後
cached = matcherFromTokens( match[i] );
變成了一個超大的嵌套閉包
5: 通過matcherFromGroupMatchers這個函數來生成最終的比對器
通過matcherFromGroupMatchers的處理最直接的就是能看出,elementMatchers, setMatchers 2個結果不需要再傳回出去,直接形成curry的方法,在内部就合并參數
外面就直接調用了,這樣
compileFunc 一直是持有elementMatchers, setMatchers 的引用的,這個設計的手法還是值得借鑒的
執行期:
至此之前的5個步驟都是編譯成函數處理器的過程,然後就是開始執行了
粗的原理就是把直接分解出來的seed種子合集丢到這個處理器中,然後處理器就會根據各種關系進行分解比對
進而得到結果集
superMatcher:
抽出第一個seed元素,p
然後把p丢到atrr是過濾篩選器中去比對下,看看是否能找到對應的這個屬性
當然還是繼續從右往左邊比對過濾了
一次是【name=aaron】 => div => from
matchers[i] => Expr.filter.ATTR =>
p.getAttribute(‘name=aaron’) => 得到結果
如果比對失敗,自然就退出了 return false ,就不需要在往前找了 ,然後再次遞歸seed
如果成功,就需要再深入的比對了
因為是從右到左逐個比對,是以往前走就會遇到關系選擇器的問題,
那麼jQuery把四種關系 > + ~ 空的處理給抽出一個具體的方法就是addCombinator
sizzle對選擇器的大概是思路:
分解所有的選擇器為最小單元,從右往左邊開始挑出一個浏覽器的API能快速定位的元素TAG,ID,CLASS節點,這樣就能确定最終的元素跟這個元素是有關系的
然後把剩餘的選擇器單元開始生成一個比對器,主要是用來做篩選,最後根據關系分組
如果就依次比對往上查找,通過關系處理器定位上一個節點的元素,通過普通比對器去确定是否為可選的内容
本文轉自艾倫 Aaron部落格園部落格,原文連結:http://www.cnblogs.com/aaronjs/p/3857899.html,如需轉載請自行聯系原作者