2011-10-29 5 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

여러 가지 이유로 느립니다. 가장 확실한 사실은 아무도 그것을 사용하지 않는다는 것입니다. 그래서 훨씬 더 적은 시간이 최적화에 소비되었습니다. 다른 문제는 대규모 재진입 (re-entrant)이며, 모든 노드는 JS로 호출하여 필터 기능을 실행해야합니다.

revision three of the benchmark을 보면, 반복자가 수행하는 작업을 getElementsByTagName("*")을 사용하여 다시 구현 한 다음 동일한 필터를 실행하고 있음을 알 수 있습니다. 결과가 보여 주듯이, 훨씬 더 빠릅니다. Going JS -> C++ -> JS가 느립니다.

JS (getElementsByTagName 경우) 또는 C++ (querySelectorAll 경우)로 완전히 노드를 필터링하는 것은 반복적으로 경계를 교차하여 수행하는 것보다 훨씬 빠릅니다.

또한 querySelectorAll에서 사용되는 선택기 일치는 비교적 똑똑합니다. 오른쪽에서 왼쪽으로 매칭되며 사전 계산 된 캐시를 기반으로합니다 (대부분의 브라우저는 클래스가있는 모든 요소의 캐시 된 목록을 반복합니다. klass "라고 입력하고 a 요소인지 확인한 다음 부모가 div인지 확인하십시오. 따라서 전체 문서를 반복 할 필요가 없습니다.

NodeIterator를 언제 사용합니까? 기본적으로 JavaScript는 절대 사용하지 마십시오. Java와 같은 언어 (의심 할 여지없이 NodeIterator라는 인터페이스가있는 주된 이유)에서와 마찬가지로 필터는 필터와 동일한 언어로되어 있기 때문에 다른 어떤 것보다 빠르다. 그 외에도 노드 객체를 만드는 메모리 사용량이 노드의 내부 표현보다 훨씬 큰 언어의 경우에만 의미가 있습니다.