CSS选择器从右向左的匹配规则

下面这个栗子,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

image

 

假如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元素的查找与匹配(固然其中作了不少优化),性能获得了很大的提高。

 

欢迎批评指正。

相关文章
相关标签/搜索