什么时候NodeList是活的,什么时候是静态的?

从NodeList的 MDN:

在某些情况下,NodeList是一个实时集合,这意味着DOM中的变化反映在集合中。 例如,Node.childNodes是活动的:

var parent = document.getElementById('parent'); var child_nodes = parent.childNodes; console.log(child_nodes.length); // let's assume "2" parent.appendChild(document.createElement('div')); console.log(child_nodes.length); // should output "3" 

在其他情况下,NodeList是一个静态集合,意味着DOM中的任何后续更改都不会影响集合的内容。 document.querySelectorAll返回一个静态的NodeList。

所以….有点讨厌! 有什么中央参考哪些方法返回实时列表,哪些返回静态列表,而不必单独检查DOM API的各个部分? 这里有什么规定吗?

关于每个方法的详细信息,如果它是否存在,但似乎没有一个标准的惯例来确定它。

document.getElementsByClassName()是一个HTMLCollection ,并且是活的。

document.getElementsByTagName()是一个HTMLCollection ,并且是活的。

document.getElementsByName()是一个NodeList并且是活的。

document.querySelectorAll()是一个NodeList并且不是活的。

HTMLCollection似乎永远是活的

HTMLCollection是一个节点列表。 单个节点可以通过序号索引或节点的名称或ID属性进行访问。

注意:假设HTML DOM中的集合是活的,意味着当底层文档发生更改时,它们会自动更新。

http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-75708506

所以,HTML集合总是 “在DOM中”,而nodeList是一个更通用的构造,可能或不可能在DOM中。

一个NodeList对象是一个节点的集合… NodeList接口提供了一个有序的节点集合的抽象,没有定义或约束如何实现这个集合。 DOM中的NodeList对象是活的。

http://www.w3.org/TR/DOM-Level-3-Core/core.html#td-live

听起来不错,对吧?

集合是表示DOM节点列表的对象。 集合可以是实时的也可以是静态的。 除非另有说明,收集必须是现场的。

http://www.w3.org/TR/2012/WD-dom-20120405/#collections

所以静态集合将在规范中被指示。 所以,通过这个逻辑, document.querySelectorAll()是一个集合,但它不在 DOM中。 因为虽然集合可能或不可能是活的,但DOM中的集合必须是活的…这种区别不是很有帮助。

那么,这是一个快速的方法来确定一个collection是否存在; 它将集合的一个成员的克隆附加到DOM (所以它将匹配select器),并检查长度是否改变,然后将其删除(所以页面不受影响)

 function isLive(collection) { if (collection.length < 1) { return undefined; //inconclusivw } let body = document.getElementsByTagName('body')[0]; let l1 = collection.length; let clone = collection.item(0).cloneNode(); clone.style.display = "none"; body.appendChild(clone); let l2 = collection.length; body.removeChild(clone); return l2 !== l1; } 

DEMO

HTML

 <html><body> <div class="c" name="mydiv">C1</div> <div class="c" name="mydiv">C2</div> </body></html> 

JS

 divs1=document.getElementsByClassName('c'); console.log(divs1.toString());//"[object HTMLCollection]" divs2=document.querySelectorAll('.c'); console.log(divs2.toString());//"[object NodeList]" divs3=document.getElementsByName('mydiv'); console.log(divs3.toString());//"[object NodeList"] console.log(isLive(divs1));//true console.log(isLive(divs2));//false console.log(isLive(divs3));//true 

我不知道是否有一个中心的参考,但这个博客文章说:

document.getElementsByTagName()document.getElementsByTagNameNSdocument.getElementsByClassName()是返回“活动”节点列表的唯一可用选项。 看这些方法,你可能会气馁,但不要这样做。