5

Doing some research regarding live or static DOM collection. What I got was that a NodeList is a live collection when changes in the DOM are reflected in the collection. It is a static collection when this is not the case.

Was reading the following question:

When is NodeList live and when is it static?

The answer stated that HTMLCollections are always live and NodeList may be either live or static.

However is this still the case? I can't seem to reproduce a static collection. For example document.querySelectorAll is supposed (source: answer from the link earlier given) to return a static collection but seems live to me in the following example:

const elements = document.querySelectorAll('.hi');

function change() {
  document.querySelectorAll('.hi')[0].style.backgroundColor = 'red';
}

function checkvalue() {
  console.log(elements[0].style.backgroundColor);
}
<div class="hi">test</div>
<div class="hi">test</div>

<button onclick="change()">change</button>
<button onclick="checkvalue()">checkvalue</button>

In this example the elements NodeList still updates the color red and thus the elements NodeList seems to be live.

Question:

Are there still live and static DOM collections, or do only live ones exist nowadays? If static ones still exist please give an example.

Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155

1 Answers1

13

You're misunderstanding what's live/static: It's the collection that's live or static, not the elements in the collection.

If you do:

const spans = document.getElementsByTagName("span");

and later, you add a new span to the DOM, the value of spans.length will increase because that new span is added to the collection; HTMLCollection instances are live.

But if you do:

const spans = document.querySelectorAll("span");

and later, you add a new span to the DOM, the value of spans.length will not increase, because the new span isn't added to the list; the NodeList from querySelectorAll is static.

The elements are live either way.

Example:

const coll = document.getElementsByTagName("span");
const list = document.querySelectorAll("span");
console.log("(before) coll.length = " + coll.length);
console.log("(before) list.length = " + list.length);

console.log("Adding another span");
document.body.appendChild(
  document.createElement("span")
);
console.log("(after)  coll.length = " + coll.length);
console.log("(after)  list.length = " + list.length);
<span></span>

The DOM doesn't really have static elements. If you need something similar, you could copy the elements so they weren't in the DOM anymore, so changes you make (to the copy) don't affect the one in the DOM:

const elements = Array.prototype.map.call(
    document.querySelectorAll('.hi'),
    element => element.cloneNode(true)
);

Example:

const elements = Array.prototype.map.call(
  document.querySelectorAll('.hi'),
  element => element.cloneNode(true)
);

function change() {
  document.querySelectorAll('.hi')[0].style.backgroundColor = 'red';
}

function checkvalue() {
  console.log(elements[0].style.backgroundColor);
}
<div class="hi">test</div>
<div class="hi">test</div>

<button onclick="change()">change</button>
<button onclick="checkvalue()">checkvalue</button>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875