我已经编写了以下代码:

var foo=document.createElement("div");

var childs=foo.getElementsByTagName("*");

console.log(childs.length);//0 OK

var a=document.createElement("a");

foo.appendChild(a);

console.log(childs.length);//1 WTF?

fiddle :http://jsfiddle.net/RL54Z/3/

我不必在第五行和第六行之间编写childs=foo.getElementsByTagName("*");,从而可以更新childs.length

怎么会这样?

最佳答案

DOM中的大多数节点列表(例如从getElementsBy*querySelectorAllNode.childNodes返回)不是简单的Arrays而是NodeList对象。 NodeList对象通常是“事件的”,因为对文档的更改会自动传播到Nodelist对象。 (异常(exception)是querySelectorAll的结果,该结果不是实时的!)

因此,如您在示例中所看到的,如果检索所有a元素的NodeList,然后向文档中添加另一个a元素,则a将出现在NodeList对象中。

这就是为什么在同时对文档进行更改的同时遍历NodeList是不安全的原因。例如,此代码将以令人惊讶的方式运行:

var NodeListA = document.getElementsByTagName('a');

for (var i=0; i<NodeListA.length; ++i) {
   // UNSAFE: don't do this!
   NodeListA[i].parentNode.removeChild(NodeListA[i]);
}

将会发生什么,您最终将跳过元素!从NodeList的末尾向后迭代,或者将NodeList复制到一个普通的数组(不会更新),然后使用该数组。

Mozilla MDC site上了解有关NodeLists的更多信息。

关于javascript - getElementsByTagName ("*")总是更新吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11271598/

10-11 13:02