我一直相信(尽管我现在怀疑这些信念的有效性):
div.name
速度比:
.name
但是,最近我读到大多数CSS选择器引擎都是从右向左读取的,在这种情况下,第一个示例实际上不会更慢吗?因为选择器引擎会简单地找到每个具有一类名称的元素,然后必须识别出哪些是
div
?CSS选择器引擎通常阅读哪种方式?从左到右还是从右到左?如果他们通常从右到左阅读,是否有人可以向我解释原因(我看不到从选择器引擎的角度来从右向左阅读有何意义)?
最佳答案
但是我最近读到,大多数CSS选择器引擎都是从右到左读取的,在这种情况下,第一个示例实际上不会更慢吗?
大致了解CSS选择器引擎的哪种方式?从左到右还是从右到左?并且,如果他们通常从右到左阅读,是否有人可以向我解释原因(我看不到从选择器引擎的角度来从右向左阅读有何意义)?
坦白说,要确定哪个选择器在给定的浏览器中变慢,几乎不可能。性能趋于波动并且不可预测,尤其是在这种微观规模和不可预测的文档结构下。即使我们讨论理论性能,它最终也取决于实现。
话虽如此,如Boris Zbarsky's answer to this other question和Guffa's answer to yours所示,典型的浏览器(当前适用于所有主要布局引擎)采用一个元素并评估所有候选选择器以查看其匹配的选择器,而不是查找一个与给定选择器匹配的元素集。这是一个微妙但非常重要的区别。鲍里斯(Boris)提供的技术说明不仅详细到令人难以置信,而且权威性强(在他使用Firefox使用的引擎Gecko的过程中),所以我强烈建议您阅读它。
但是我认为我应该解决您的问题中似乎另一个需要关注的问题:
因为选择器引擎会简单地找到每个具有一类名称的元素,然后必须标识哪些是div
?
以及Patrick McElhaney's comment:
链接的问题解释了为什么选择器通常是从右到左读取的,所以#foo ul.round.fancy li.current
是从li.current, ul.round.fancy, #foo
读取的,但是它真的在每个元素(.current, li, .fancy, .round, ul, #foo
)中从右到左读取吗?应该吗
我从未实现CSS,也从未见过其他浏览器如何实现CSS。从上面链接的答案中我们确实知道,浏览器使用从右到左的匹配来遍历选择器中的组合器,例如本示例中的>
组合器:
section > div.second > div.third
如果元素不是
div.third
,则没有检查它的父元素是div.second
父元素是section
的点。但是,我不相信这种从右到左的顺序会一直向下钻到简单的选择器级别。换句话说,我不认为浏览器会在从右到左求值的一系列简单选择器序列(也称为复合选择器)的每个部分中使用从右到左的求值方式,这些选择器序列由组合器。
例如,考虑以下人为设计和高度夸大的选择器:
div.name[data-foo="bar"]:nth-child(5):hover::after
现在,不能保证浏览器一定会按照以下顺序检查元素的这些条件:
指针是否在此元素上?
此元素是其父项的第5个孩子吗?
此元素是否具有值为
data-foo
的bar
属性?此元素是否具有
name
类?这是
div
元素吗?除了在选择器上杂乱无章的简单选择器之外,该选择器在功能上与上面的相同,也不必按以下顺序进行评估:
div:hover[data-foo="bar"].name:nth-child(5)::after
此元素是其父项的第5个孩子吗?
此元素是否具有
name
类?此元素是否具有值为
data-foo
的bar
属性?指针是否在此元素上?
这是
div
元素吗?完全没有理由出于性能原因而强制执行此类命令。实际上,我认为通过优先选择某些简单选择器(无论它们在序列中的什么位置),可以提高性能。 (您还将注意到,没有考虑
::after
,这是因为伪元素不是简单的选择器,甚至从不输入匹配方程式。)例如,众所周知,ID选择器是最快的。好吧,鲍里斯(Boris)在对链接问题的回答的最后一段中这样说:
还要注意,浏览器已经做了其他优化,甚至可以避免匹配绝对不匹配的规则。例如,如果最右边的选择器具有一个ID,并且该ID与元素的ID不匹配,则在壁虎中根本不会尝试将该选择器与该元素进行匹配:尝试的“具有ID的选择器”集合来自对元素ID的哈希表查找。因此,仅考虑最右边选择器的标记/类/ ID,这就是70%的规则很有可能匹配,但仍然不匹配。
换句话说,是否具有如下所示的选择器:
div#foo.bar:first-child
或这个:
div.bar:first-child#foo
壁虎将始终先检查ID和类,而不管其在序列中的位置。如果该元素没有ID和与选择器匹配的类,则会立即将其丢弃。如果你问我,很快就可以了。
那只是壁虎为例。这在实现之间也可能有所不同(例如,Gecko和WebKit可能与Trident甚至Presto有所不同)。当然,有一些供应商普遍同意的策略和方法(首先检查ID可能没有区别),但是细节上可能有所不同。
关于css - 选择器引擎朝哪个方向准确读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37003201/