来自 MDN for NodeList:
在某些情况下,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 中,也可能不在 DOM 中。
节点列表对象是节点的集合...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
(因此它将与选择器匹配),并检查长度是否更改,然后将其删除(因此页面不受影响)
演示
function isLive(collection) {
if (HTMLCollection.prototype.isPrototypeOf(collection)) return true // HTMLCollections are always live
const length = collection.length;
if (!length) return undefined; // Inconclusive
const el = collection.item(0);
const parent = el.parentNode;
const clone = el.cloneNode();
clone.style.setProperty('display', 'none', 'important');
parent.appendChild(clone);
const live = collection.length !== length;
parent.removeChild(clone);
return live;
}
const divs1 = document.getElementsByClassName('c');
const divs2 = document.getElementsByTagName('span');
const divs3 = document.getElementsByName('notFound');
const divs4 = document.querySelectorAll('.c');
console.log("document.getElementsByClassName('c'):", divs1.toString()); // [object HTMLCollection]
console.log("document.getElementsByTagName('notFound'):", divs2.toString()); // [object HTMLCollection]
console.log("document.getElementsByName('notFound'):", divs3.toString()); // [object NodeList]
console.log("document.querySelectorAll('.c'):", divs4.toString()); // [object NodeList]
console.log('isLive(divs1)', isLive(divs1)); // true
console.log('isLive(divs2)', isLive(divs2)); // true
console.log('isLive(divs3)', isLive(divs3)); // undefined
console.log('isLive(divs4)', isLive(divs4)); // false
<html>
<body>
<div>
<div class="c">C1</div>
<div class="c">C2</div>
</div>
<div>
<div class="c">C3</div>
<div class="c">C4</div>
</div>
</body>
</html>
是否有中心引用,但这些是我知道的返回 HTMLCollection
s 并活NodeList
s 的方法和属性:
方法
-
parentNode.getElementsByClassName()
- 返回HTMLCollection
-
parentNode.getElementsByTagName()
- 返回HTMLCollection
-
parentNode.getElementsByTagNameNS()
- 返回HTMLCollection
-
document.getElementsByName()
- 返回NodeList
性能
-
parentNode.children
- 返回一个HTMLCollection
-
Node.childNodes
- 返回NodeList