NodeList 什么时候上线,什么时候是静态的?

When is NodeList live and when is it static?

来自 NodeList 的 MDN:

In some cases, the NodeList is a live collection, which means that changes in the DOM are reflected in the collection. For example, Node.childNodes is live:

 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"

In other cases, the NodeList is a static collection, meaning any subsequent change in the DOM does not affect the content of the collection. document.querySelectorAll returns a static NodeList.

所以....有点烦人!是否有关于哪些方法 return 实时列表和哪些方法 return 静态列表的中心参考,而无需单独检查 DOM API 的所有不同部分?这里有规则吗?

我不知道是否有中心参考,但这些是我所知道的 return HTMLCollections 和 live NodeLists:[=24 的方法和属性=]

方法

  • parentNode.getElementsByClassName() - return 一个 HTMLCollection
  • parentNode.getElementsByTagName()   - return 一个 HTMLCollection
  • parentNode.getElementsByTagNameNS() - return 一个 HTMLCollection
  •   document.getElementsByName()      - return一个NodeList

属性

  • parentNode.children   - return 一个 HTMLCollection
  •       Node.childNodes - return一个NodeList

有关每个方法的详细信息,如果它是实时的,但似乎没有确定它的标准约定。

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

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

document.getElementsByName()NodeList 并且正在直播。

document.querySelectorAll()NodeList 不是 直播。

HTMLCollection似乎总是在线

An HTMLCollection is a list of nodes. An individual node may be accessed by either ordinal index or the node's name or id attributes.

Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.

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

因此,HTML 集合 总是 “在 dom 中”,而 nodeList 是一个更通用的结构,可能或可能不在 DOM.

A NodeList object is a collection of nodes... The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.

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

听起来不错吧?

A collection is an object that represents a lists of DOM nodes. A collection can be either live or static. Unless otherwise stated, a collection must be live.

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

因此静态集合将在规范中如此指明。所以,按照这个逻辑,document.querySelectorAll()是一个集合,但在DOM中是而不是。因为虽然集合可能是实时的也可能不是实时的,但 in 中的集合 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>