2012-01-04 3 views
0

안전하다는 것은 document.getElementsById('*');에 의해 생성 된 NodeList가 실제 객체라는 것을 의미합니다. 일부 요소는 JS 엔진 루프를 통해 동적으로 추가되거나 제거됩니다.순수 JS에서 전체 DOM을 루핑하는 가장 빠르고 안전하며 올바른 방법은 무엇입니까?

내가하고자하는 일은 전체 DOM을 반복하는 것입니다 (이 작업은 greasemonkey 스크립트에서 수행되므로 일반적인 웹 사용에는 적합하지 않지만이 규칙이 적용됩니다). 노드 CSS가 일부 규칙과 일치하는지 확인하고 그 변화에 따라 CSS.

웹 사이트가 여러 스크립트 (이미지/뉴스 기사 변경 등)를 실행하고 있으므로 DOM 노드를 조만간 추가 및 제거하면 노드가 사라질 때가 있습니다. 처리됩니다.

그리고 내 말은 빠른에 의해

재귀 적으로 그것을 할 더 나은입니다 :
function traverseDOM(node,f) { 
    if (node.nodeType !== 1) return; 
    f.apply(node); 
    for (var i = 0; i < node.childNodes.length; i++) { 
    traverseDOM(node.childNodes[i],f); 
    } 
} 

(그러나 이것은 nodeType에 확인에 시간을 낭비) 또는 for 루프에 의해 :

nodes = document.getElementsByTagName('*'); 
for (var i=0; i<nodes.length; i++) { 
    //do my stuff 
} 

(그러나이 결국 NodeList의 끝이 변동하는 문제가 발생할 것입니다.

답변

0

JavaScript는 단일 스레드입니다. 한 번에 하나의 기능 만 실행할 수 있습니다. DOM을 반복하면서 수정하는 것은 불가능합니다.

1

에서 예를 참조하는 예입니다, 한번 시도해 주시기 바랍니다. 약 170 개의 노드에서 테스트했는데 너무 느리지는 않았지만 반드시 빠를 필요는 없습니다.

function walk (node, func) { 
    func(node); 
    node = node.childNodes[0]; 

    while (node) { 
     walk(node, func); 
     node = node.nextSibling; 
    } 
} 

var doc = document; //save a reference to the document (might be a tiny bit faster... not sure) 
var bd = doc.body; //start to walk the DOM from the body 
var o = doc.getElementById('some_div'); //some div to output to 
var arr = []; //array to collect all nodes 

walk(bd, function(n){ 
    if (n.nodeType === 1) { 
     n.style.border = "2px solid red"; //change the border color for each node that was found 
     o.innerHTML += "<pre>" + n.nodeName + "</pre>"; //output each node's name to a div 
     arr.push(n); //add each node to the array 
    } 
}); 

console.log(arr.length); //log the total number of nodes affected