2011-10-29 6 views
6

Benchmarkを使用するには、今のいずれかNodeIterator年代が吸うか、私はそれが間違ってやっている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  
} 

対QSA & .forEachを比較します。

質問:NodeIteratorはいつ使用しますか?

あなたが知らない場合、DOM4は、NodeIteratorが何であるかを指定します。

答えて

9

さまざまな理由から遅いです。最も明白なのは、誰もそれを使用しないので、それを最適化するために費やされる時間がはるかに短いことです。もう1つの問題は、大規模にリエントラントであり、すべてのノードがJSを呼び出してフィルタ関数を実行する必要がないことです。

revision three of the benchmarkを見ると、イテレータの動作をgetElementsByTagName("*")で再実装した後、同じフィルタを実行していることがわかります。結果が示すように、それは大幅に高速です。 Going JS - > C++ - > JSが遅いです。

JSでノード全体をフィルタリングする場合(getElementsByTagNameの場合)またはC++(querySelectorAllの場合)は、繰り返し境界を越えることでノードをフィルタリングするよりもはるかに高速です。

querySelectorAllで使用されているようにセレクタのマッチングも比較的スマートです:右から左へのマッチングを行い、あらかじめ計算されたキャッシュに基づいています(ほとんどのブラウザは、 klass "の場合は、a要素かどうかを確認して、親がdivかどうかを確認してください。したがって、ドキュメント全体を反復処理しなくても構いません。

NodeIteratorをいつ使用するのですか? JavaScriptでは基本的に決して決してありません。 Javaのような言語(間違いなくNodeIteratorというインターフェースが存在する主な理由)では、あなたのフィルターはフィルターと同じ言語になるため、他のものと同じくらい速くなるでしょう。それとは別に、Nodeオブジェクトを作成するメモリ使用量がNodeの内部表現よりもはるかに大きい言語では、意味をなさない唯一の時間があります。

関連する問題