CSS 的后代选择器本身就是一种在标准里面不那么推荐的方式。
首先,对浏览器来说,ID 选择器 #xx 是最快的,其次是 class 选择器、html 元素选择器等。
那为什么从右向左的规则要比从左向右的高效?
如图:
假如 DOM 的结构如上图,匹配规则是 .mod-nav h3 span。
若从左向右的匹配,过程是:从 .mod-nav 开始,遍历子节点 header 和子节点 div,然后各自向子节点遍历。在右侧 div 的分支中,最后遍历到叶子节点 a ,发现不符合规则,需要回溯到 ul 节点,再遍历下一个 li-a,假如有 1000 个 li,则这 1000 次的遍历与回溯会损失很多性能。
再看看从右至左的匹配:先找到所有的最右节点 span,对于每一个 span,向上寻找节点 h3,由 h3再向上寻找 class=mod-nav 的节点,最后找到根元素 html 则结束这个分支的遍历。
很明显,两种匹配规则的性能差别很大。之所以会差别很大,是因为从右向左的匹配在第一步就筛选掉了大量的不符合条件的最右节点(叶子节点);而从左向右的匹配规则的性能都浪费在了失败的查找上面。
当然这是比较明显情况,如果在叶子上存在多个不符合条件的 span,从右向左的规则也会走一些弯路(这时就需要优化 CSS 选择器了)。但平均来说它还是更高效,因为大多时候,一个 DOM 树中,符合匹配条件的节点(如 .mod-nav h3 span)远少于不符合条件的节点。
但是后来人们发现这种方式很不符合人类自然的思考方式,所以在建造 web 的时候更喜欢采用看起来比较有条理的更加像后端程序的层次结构方式命名,类似 #fuck .you a {...}。
但是根据实践,大家发现这样基本是在 自high,因为别人在改 CSS 的时候是不会去看你写的 CSS 的,都是直接浏览器定位到位于哪一行,直接过去改代码块,反正一眼就能看懂。
其实不用纠结这些,CSS 的解析时间跟 js 执行时间相比就像 PHP 代码的运行时间和数据库、I/O运行时间对比一样,不是一个数量级,完全不用担心。