2011-10-29 48 views
6

Benchmark比較QSA & .forEach VS一個NodeIterator當使用NodeIterator

toArray(document.querySelectorAll("div > a.klass")).forEach(function (node) { 
    // do something with node 
}); 

var filter = { 
    acceptNode: function (node) { 
     var condition = node.parentNode.tagName === "DIV" && 
      node.classList.contains("klass") && 
      node.tagName === "A"; 

     return condition ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT 
    } 
} 
// FIREFOX Y U SUCK 
var iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, filter, false); 
var node; 
while (node = iter.nextNode()) { 
    // do thing with node  
} 

現在要麼NodeIterator的吸或我做錯了。

問題:什麼時候應該使用NodeIterator

如果你不知道,DOM4指定什麼NodeIterator是。

回答

9

由於各種原因,速度很慢。最明顯的是沒有人使用它,因此只需要很少的時間就可以優化它。另一個問題是它大量重入,每個節點都必須調用JS並運行過濾器函數。

如果你看看revision three of the benchmark,你會發現我已經使用getElementsByTagName("*")添加了迭代器的重做實例,然後在其上運行相同的過濾器。結果顯示,它非常快速。去JS - > C++ - > JS很慢。

完全通過JS(getElementsByTagName)或C++(querySelectorAll)情況下完全過濾節點要比通過重複穿越邊界快得多。

另請注意,querySelectorAll所使用的選擇器匹配相對比較智能:它從左到右進行匹配,並基於預先計算的緩存(大多數瀏覽器將迭代所有元素的緩存列表, klass「,檢查它是否爲a元素,然後檢查父代是否爲div),因此它們甚至不會反覆遍歷整個文檔。

鑑於此,何時使用NodeIterator?至少在JavaScript中基本上不會。在諸如Java之類的語言中(無疑是有一個名爲NodeIterator的接口的主要原因),它可能與其他任何東西一樣快,因爲那時你的過濾器將與過濾器使用相同的語言。除此之外,唯一有意義的是在創建節點對象的內存使用量遠遠大於節點內部表示的語言中。