0

安全我的意思是 NodeList 创建的事实document.getElementsById('*');是一个活动对象。当 JS 引擎循环通过它时,会动态添加或删除一些元素。

我打算做的事情是遍历整个 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 的波动提示)

4

3 回答 3

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
于 2012-01-04T13:21:43.693 回答
0

JavaScript 是单线程的。一次只能运行一个函数。当您遍历 DOM 时,它应该是不可能被修改的。

于 2012-01-04T11:35:19.003 回答
0

有一个 w3c 元素遍历规范,请参见http://www.w3.org/TR/ElementTraversal/#example-3.2中的示例

于 2012-01-04T11:43:01.870 回答