2012-04-11 20 views
9

我一直相信(雖然我現在懷疑這些信念的有效性)認爲:選擇器引擎在哪個方向讀取?

div.name 

快於:

.name 

不過我最近讀到最CSS選擇器引擎閱讀從右到左,在這種情況下,第一個例子實際上會不會變慢?由於選擇器引擎會簡單地找到每個具有一個類名稱的元素,然後必須確定其中哪些是div s?

CSS選擇器引擎讀取哪種方式?從左到右還是從右到左?如果他們通常從右向左閱讀,有人可以給我一個解釋,爲什麼(我不明白從選擇器引擎的右到左閱讀是否有意義)?

+0

看起來好像這個問題已被問:http://stackoverflow.com/questions/5797014/css-selectors-parsed-right-to-left-why – Joe 2012-04-11 13:00:36

+0

第一個說:「檢查類名'名稱'在所有DIV元素「,第二個說」在** ALL **元素中檢查類名「名稱」。對我來說第一個會更快沒有? – rlemon 2012-04-11 13:05:22

+1

鏈接的問題解釋了爲什麼選擇器是從右至左閱讀的,因此'#foo ul.round.fancy li.current'被讀爲'li.current,ul.round.fancy,#foo',但是它是真的是從每個元素中的從右到左('.current,li,.fancy,.round,ul,#foo')?它應該是? – 2012-04-11 13:09:22

回答

10

不過我最近讀了由右至左讀最CSS選擇器引擎,在這種情況下也不會第一個例子實際上是慢?

CSS選擇器引擎通常讀取哪種方式?從左到右還是從右到左?如果他們通常從右向左閱讀,有人可以給我一個解釋,爲什麼(我不明白從選擇器引擎的右到左閱讀是否有意義)?

坦率地說,幾乎不可能告訴哪個選擇器在給定的瀏覽器中速度較慢,在瀏覽器中要少得多。性能趨於波動且難以預測,特別是在這種微觀尺度下以及不可預知的文檔結構。即使我們談論理論表現,它最終取決於實施。

話雖如此,如圖Boris Zbarsky's answer to this other questionGuffa's answer to yours,一個典型的瀏覽器(這是目前所有主要的佈局引擎的確如此)需要的元素,並評估所有候選選擇,看看它匹配哪些,而不是尋找一個匹配給定選擇器的元素集。這是一個微妙但非常重要的區別。 Boris提供的技術解釋不僅非常詳細,而且還具有權威性(因爲他在Firefox上使用的引擎Gecko上工作),所以我強烈建議閱讀它。

但我想我應該解決什麼似乎是在你的問題的另一個問題:

由於選擇器引擎只會找到一個類名的每一個元素,然後必須確定其中哪些人div s?

除了Patrick McElhaney's comment

鏈接的問題,解釋了爲什麼選擇讀從右到左一般,所以#foo ul.round.fancy li.currentli.current, ul.round.fancy, #foo,但它確實讀從右到左內每個元素(.current, li, .fancy, .round, ul, #foo)?它應該是?

我從來沒有實現CSS,也沒有看到其他瀏覽器如何實現它。我們從以上鍊接的答案知道瀏覽器使用權到左匹配選擇範圍內跨組合程序走,比如>組合子在這個例子:

section > div.second > div.third 

如果一個元素是不是一個div.third,然後沒有意義檢查其父項是否爲div.second,其父項是section

但是,我不認爲這個從右到左的順序一直鑽到簡單的選擇器級別。換句話說,我並不認爲瀏覽器在複合選擇器的系列的右對齊評估中對簡單選擇器序列(也稱爲複合選擇器)的每個部分都使用從右到左的評估由組合器分隔。

例如,考慮這個做作和高度誇張的選擇:

div.name[data-foo="bar"]:nth-child(5):hover::after 

現在,誰也不能保證一個瀏覽器將一定檢查這些條件按下列順序的元素:

  1. 指針在這個元素上?
  2. 此元素是其父項的第5個孩子嗎?
  3. 此元素是否具有值爲bardata-foo屬性?
  4. 這個元素有一個name類嗎?
  5. 這是一個div元素?

也將這個選擇器,它是功能相同上述除以其簡單選擇器周圍錯雜,一定按照以下順序進行評價:

div:hover[data-foo="bar"].name:nth-child(5)::after 
  1. 這是元件其父母的第五個孩子?
  2. 這個元素有一個name類嗎?
  3. 此元素是否具有值爲bardata-foo屬性?
  4. 是指向這個元素的指針嗎?
  5. 這是一個div元素?

根據性能原因,這樣的訂單根本沒有理由執行。事實上,我認爲首先選擇某種簡單的選擇器會提高性能,而不管它們在哪個序列中。 (您還會注意到::after未被考慮 - 這是因爲僞元素不是簡單的選擇器,甚至從未進入匹配等式。)

例如,衆所周知ID選擇器是最快的。好了,鮑里斯說,這在他的回答的最後一段的鏈接的問題:

注意還存在其他的優化瀏覽器已經做,以避免甚至試圖匹配肯定不會匹配規則。例如,如果最右邊的選擇器有一個id,並且該id與該元素的id不匹配,那麼將不會嘗試將該選擇器與Gecko中的該元素進行匹配:嘗試的「具有ID的選擇器」集合來自元素ID的哈希表查找。所以這是70%的規則有很好的匹配的機會,仍然不匹配後,只考慮最右邊的選擇器的標記/類/ ID。

換句話說,無論你有一個選擇,看起來像這樣:

div#foo.bar:first-child 

或者這樣:

div.bar:first-child#foo 

壁虎會總是檢查ID和類第一,不管它在序列中的位置如何。如果元素沒有ID和一個與選擇器相匹配的類,那麼它立即被丟棄。如果你問我,相當不錯。

這只是Gecko的一個例子。這在實現中也可能有所不同(例如,Gecko和WebKit可能與三叉戟甚至Presto有所不同)。當然有供應商普遍認同的策略和方法(首先檢查ID不太可能有區別),但小細節可能不同。

6

選擇器引擎不會查找要應用規則的元素,它會查找適用於特定元素的規則。因此,從右向左閱讀選擇器是有意義的。

一個選擇是這樣的:

div span.text a.demo 

將使選擇器引擎做這些檢查,看是否選擇適用於某個元素:

  • 它是一個a元素與類demo
  • 它有一個span元素與text類的祖先嗎?
  • 該元素是否具有一個div元素的祖先?
+1

+1,但它並沒有真正解決從簡單/複合選擇器級別是否完成從右到左的順序。 – BoltClock 2012-04-11 13:24:16

+0

@ BoltClock'saUornorn:結論是無所謂。由於引擎一次只查看一個元素,因此檢查元素類型或元素屬性之間沒有相關的性能差異。 – Guffa 2012-04-12 11:16:34