getElementsByTagName(“*”)总是更新?

时间:2012-06-30 05:07:11

标签: javascript dom getelementsbytagname

我已经制作了这段代码:

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?

小提琴:http://jsfiddle.net/RL54Z/3/

我不必在第五行和第六行之间写{​​{1}},以便更新childs=foo.getElementsByTagName("*");

怎么可能?

2 个答案:

答案 0 :(得分:3)

如果您阅读documentation,那就不会感到惊讶

  

返回具有给定标记名称的元素列表。搜索指定元素下面的子树,不包括元素本身。返回的列表是实时的,这意味着它会自动使用DOM树更新自己。因此,不需要使用相同的元素和参数多次调用element.getElementsByTagName。

答案 1 :(得分:3)

DOM中的大多数节点列表(例如,从getElementsBy*querySelectorAllNode.childNodes返回)不是简单的数组,而是NodeList个对象。 NodeList个对象通常是" live",因为对文档的更改会自动传播到Nodelist对象。 (例外是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复制到plain Array(不会更新),然后使用它。

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