我已经制作了这段代码:
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("*");
。
怎么可能?
答案 0 :(得分:3)
如果您阅读documentation,那就不会感到惊讶
返回具有给定标记名称的元素列表。搜索指定元素下面的子树,不包括元素本身。返回的列表是实时的,这意味着它会自动使用DOM树更新自己。因此,不需要使用相同的元素和参数多次调用element.getElementsByTagName。
答案 1 :(得分:3)
DOM中的大多数节点列表(例如,从getElementsBy*
,querySelectorAll
和Node.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的更多信息。