jQuery選擇器源碼解讀(六):Sizzle選擇器匹配邏輯分析
近期看了一些網(wǎng)上關(guān)于Sizzle的分析文章,就匹配次序往往就說(shuō)使用了從右到左的逆向匹配法,但是具體如何并沒(méi)有詳細(xì)介紹,或者就像我之前的幾篇文章一樣,就代碼一行一行做詳細(xì)介紹,但缺乏整體概念,這里就jQuery-1.10.2版本的Sizzle的匹配邏輯(預(yù)編譯結(jié)果)做一整體說(shuō)明,這里就不談過(guò)多的細(xì)節(jié)了。
Sizzle的匹配過(guò)程采用的是以從右到左的逆向匹配法為基礎(chǔ)的改進(jìn)版本,因?yàn)镠TML的搜索畢竟和文本匹配有差異,它有自己獨(dú)特的一面,所以,需要針對(duì)HTML的搜索進(jìn)行優(yōu)化。在此先申明一點(diǎn),下面所說(shuō)的關(guān)系選擇器是指W3C中的Combinator選擇器,因本人覺(jué)得用關(guān)系選擇器這個(gè)名字要比其它更加貼近實(shí)際意義,故用此命名。
1、簡(jiǎn)單介紹一下Sizzle編譯執(zhí)行的兩個(gè)主要函數(shù):
a) matcherFromTokens——針對(duì)一個(gè)塊選擇器生成執(zhí)行函數(shù),所謂塊選擇器就是不包含逗號(hào)分隔的選擇器字符串。
b) matcherFromGroupMatchers——將不同的塊選擇器生成的最終執(zhí)行函數(shù),該函數(shù)還負(fù)責(zé)將最終結(jié)果過(guò)濾掉重復(fù)對(duì)象。
2、matcherFromTokens函數(shù)針對(duì)不同類(lèi)型的選擇器產(chǎn)生不同的執(zhí)行函數(shù)。若包含偽類(lèi),則返回setMatcher,否則返回的是elementMatcher,代碼通過(guò)鑒別matcher是否包含expando屬性來(lái)區(qū)別setMatcher和elementMatcher:
a) 針對(duì)非偽類(lèi)且非關(guān)系選擇器,直接從左到右依次生成執(zhí)行函數(shù),各函數(shù)作為同一個(gè)matchers數(shù)組的不同元素存在。
b) 針對(duì)關(guān)系選擇器,將會(huì)把之前生成的matchers壓入一個(gè)新的matchers數(shù)組中。
c) 針對(duì)偽類(lèi)選擇器,將通過(guò)setMatcher函數(shù)生成一個(gè)執(zhí)行函數(shù),調(diào)用setMatcher時(shí),依次傳入6個(gè)參數(shù),分別是preFilter, selector, matcher, postFilter, postFinder, postSelector。
preFilter是在執(zhí)行setMatcher函數(shù)之前已生成的matchers數(shù)組經(jīng)elementMatcher函數(shù)加工過(guò)的最終函數(shù),elementMatcher(matchers)將返回一個(gè)從后向前依次執(zhí)行每一個(gè)matchers元素函數(shù)的新函數(shù);。
selector是matchers對(duì)應(yīng)的選擇器字符串;
matcher是偽類(lèi)自身的匹配函數(shù);
postFilter是偽類(lèi)之后,到第一個(gè)偽類(lèi)或關(guān)系符之間的選擇器字符串對(duì)應(yīng)的匹配函數(shù),它是嵌套調(diào)用matcherFromTokens函數(shù)的返回結(jié)果;
postFinder是postFilter對(duì)應(yīng)選擇器之后的所有選擇器生成的匹配函數(shù),同樣也是通過(guò)嵌套調(diào)用matcherFromTokens函數(shù)的返回結(jié)果;
postSelector是postFinder對(duì)應(yīng)的選擇器字符串。
d) 若選擇器字符串中沒(méi)有偽類(lèi),那么,將返回elementMatcher(matchers)生成的最終匹配函數(shù)。
從上面的介紹可以看出,生成的執(zhí)行函數(shù)之間存在著嵌套關(guān)系,簡(jiǎn)單的講就是setMatcher包含matchers,關(guān)系選擇器匹配函數(shù)包含非偽類(lèi)且非關(guān)系選擇器匹配函數(shù)。
3、執(zhí)行過(guò)程的介紹:
a) 執(zhí)行塊選擇器的執(zhí)行函數(shù):
針對(duì)elementMatcher,從外到里從后到前依次執(zhí)行,即從最外層數(shù)組到最里層數(shù)組依次執(zhí)行,同一個(gè)數(shù)組中,從最后一個(gè)元素到第一個(gè)元素依次執(zhí)行。
針對(duì)setMatcher,先依據(jù)preFilter和selector獲得匹配結(jié)果;然后執(zhí)行matcher函數(shù)獲取匹配結(jié)果;之后,執(zhí)行postFilter函數(shù),最后,依據(jù)postFinder和postSelector獲取匹配結(jié)果。
c) 依次執(zhí)行每個(gè)塊選擇器的執(zhí)行函數(shù)后,過(guò)濾掉重復(fù)數(shù)據(jù),并返回結(jié)果。
看了上述大致過(guò)程,再去看各方法的詳細(xì)介紹應(yīng)該比較容易理解了,當(dāng)然在這里沒(méi)有談到一些細(xì)節(jié),例如初始結(jié)果集(seed)的生成及由此帶來(lái)的函數(shù)執(zhí)行邏輯細(xì)節(jié)上的差異等。
相關(guān)文章
jQuery zTree樹(shù)插件動(dòng)態(tài)加載實(shí)例代碼
這篇文章主要介紹了jQuery zTree樹(shù)插件動(dòng)態(tài)加載效果的實(shí)例代碼,需要的朋友可以參考下2017-05-05
jquery實(shí)現(xiàn)點(diǎn)擊label的同時(shí)觸發(fā)文本框點(diǎn)擊事件的方法
這篇文章主要介紹了jquery實(shí)現(xiàn)點(diǎn)擊label的同時(shí)觸發(fā)文本框點(diǎn)擊事件的方法,涉及jQuery鼠標(biāo)事件及頁(yè)面元素操作的技巧,需要的朋友可以參考下2015-06-06
jQuery 跨域訪(fǎng)問(wèn)解決原理案例詳解
這篇文章主要介紹了jQuery 跨域訪(fǎng)問(wèn)解決原理案例詳解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07
jQuery使用slideUp方法實(shí)現(xiàn)控制元素緩慢收起
這篇文章主要介紹了jQuery使用slideUp方法實(shí)現(xiàn)控制元素緩慢收起的功能,實(shí)例分析了jQuery中slideUp方法的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
jquery表單驗(yàn)證實(shí)例仿Toast提示效果
這篇文章主要介紹了jquery驗(yàn)證表單仿Toast提示效果,實(shí)現(xiàn)代碼簡(jiǎn)單易懂,非常不錯(cuò),需要的朋友可以參考下2017-03-03
Jquery+WebService 校驗(yàn)賬號(hào)是否已被注冊(cè)的代碼
在Javascirpt代碼中,調(diào)用Jquery的方法$.Ajax(function)實(shí)現(xiàn)Ajax,傳遞賬號(hào)信息給Web服務(wù),Web服務(wù)再調(diào)用數(shù)據(jù)庫(kù)操作類(lèi)查詢(xún)數(shù)據(jù)庫(kù),并返回?cái)?shù)據(jù)給前臺(tái)頁(yè)面。2010-07-07
jQuery獲取cookie值及刪除cookie用法實(shí)例
這篇文章主要介紹了jQuery獲取cookie值及刪除cookie用法,實(shí)例分析了jQuery操作cookie時(shí)域和路徑的作用,以及針對(duì)cookie的讀取與刪除技巧,需要的朋友可以參考下2016-04-04

