下面這個栗子,CSS選擇器它是如何工做的?css
.mod-nav h3 span {font-size: 16px;}
若是不知道匹配規則,可能的理解是從左向右匹配:先找到.mod-nav,而後逐級匹配h三、span,在這個過程當中若是遍歷到葉子節點都沒有匹配就須要回溯,繼續尋找下一個分支。html
但事實上,CSS選擇器的讀取順序是從右向左。性能
仍是上面的選擇器,它的讀取順序變成:先找到全部的span,沿着span的父元素查找h3,中途找到了符合匹配規則的節點就加入結果集;若是直到根元素html都沒有匹配,則再也不遍歷這條路徑,從下一個span開始重複這個過程(若是有多個最右節點爲span的話)。優化
在某條CSS規則下(好比.mod-nav h3 span),會造成一條符合規則的索引樹,樹由上至下的節點是規則中從右向左的一個個選擇符匹配的節點。索引樹遍歷的具體過程能夠看寒冬大大的一段視頻。spa
爲何從右向左的規則要比從左向右的高效?code

假如DOM的結構如上圖,匹配規則是.mod-nav h3 span。視頻
若從左向右的匹配,過程是:從.mod-nav開始,遍歷子節點header和子節點div,而後各自向子節點遍歷。在右側div的分支中,最後遍歷到葉子節點a,發現不符合規則,須要回溯到ul節點,再遍歷下一個li-a,假若有1000個li,則這1000次的遍歷與回溯會損失不少性能。htm
再看看從右至左的匹配:先找到全部的最右節點span,對於每個span,向上尋找節點h3,由h3再向上尋找class=mod-nav的節點,最後找到根元素html則結束這個分支的遍歷。blog
很明顯,兩種匹配規則的性能差異很大。之因此會差異很大,是由於從右向左的匹配在第一步就篩選掉了大量的不符合條件的最右節點(葉子節點);而從左向右的匹配規則的性能都浪費在了失敗的查找上面。索引
固然這是比較明顯狀況,若是在葉子上存在多個不符合條件的span,從右向左的規則也會走一些彎路(這時就須要優化CSS選擇器了)。但平均來講它仍是更高效,由於大多時候,一個DOM樹中,符合匹配條件的節點(如.mod-nav h3 span)遠遠遠遠少於不符合條件的節點。
jQuery從1.3版本開始使用的Sizzle引擎,它按照了CSS選擇器的匹配規則(從右至左)進行DOM元素的查找與匹配(固然其中作了不少優化),性能獲得了很大的提高。
歡迎批評指正。