2

This seems confusing, but I bet I am missing something fundamental.

Interestingly enough, the W3Schools docs are wrong and say both methods return an HTMLCollection: https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp https://www.w3schools.com/jsref/met_doc_getelementsbyname.asp <- incorrect

The Mozilla docs are correct in that byName returns a NodeList while byClassName returns an 'array like' object, aka HTMLCollection.

Found this out when I tried to run forEach on the output of byClassName and it failed.

Joshua Dance
  • 8,847
  • 4
  • 67
  • 72
  • 1
    There is many errors in W3Schools docs, just do not use this site as a source of informations. – Kamil Naja Feb 06 '20 at 08:02
  • @KamilNaja is there an easy way to block that site? They almost always show up in the first search result. – Joshua Dance Feb 06 '20 at 08:05
  • 1
    FWIW, the historical context is that the various parts of the DOM API was created by different people at different points in time (Netscape, Mozilla, Microsoft, Apple etc.) and the W3C standards committee tend to take the position of adopting an existing implementation into the spec wherever possible so the minimum number of developers need to change their browser's behavior. Also, at some point Apple got frustrated with it and started a new standards committee with Mozilla: WHATWG which is not merged back in with W3C standards.. Standards are a messy thing – slebetman Feb 06 '20 at 08:07
  • 1
    @JoshuaDance I tend to start my search with 3 letters: "MDN" to get Mozilla's docs or if you prefer Microsoft add another letter: "MSDN". This avoids returning results from w3schools – slebetman Feb 06 '20 at 08:09
  • [Why not w3schools.com?](https://meta.stackoverflow.com/questions/280478) – adiga Feb 06 '20 at 08:28

1 Answers1

3

In short, because the specification says so. For getElementsByName:

The getElementsByName(name) method takes a string name, and must return a live NodeList containing all the HTML elements in that document that have a name attribute whose value is equal to the name argument (in a case-sensitive manner), in tree order. When the method is invoked on a Document object again with the same argument, the user agent may return the same as the object returned by the earlier call. In other cases, a new NodeList object must be returned.

For getElementsByClassName:

The getElementsByClassName(classNames) method, when invoked, must return the list of elements with class names classNames for this.

(where this is usually document), and where the "list of elements" is constructed by:

The list of elements with class names classNames for a node root is the HTMLCollection returned by the following algorithm.....

Similarly, querySelectorAll returns a static NodeList.

Interestingly enough, the W3Schools docs are wrong

Not surprising - w3schools is notoriously not very reliable. Better to reference MDN or official specifications.

It's important to keep in mind the difference between the collections. On recent browsers, like you've encountered, there exists a NodeList.prototype.forEach method. No such method exists for HTMLCollections. Some of the collections are static, while some are live. The live collections (like with getElementsByClassName) can mutate themselves while you're iterating over them (unlike static collections and arrays), but the static collections (like with querySelectorAll) won't mutate themselves.

But, note that although only NodeLists have a forEach method, both collections have a Symbol.iterator property which you can iterate over with for..of:

for (const elm of document.getElementsByName('foo')) {
  // ...
}
for (const elm of document.getElementsByClassName('foo')) {
  // ...
}
console.log('No errors');
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • 1
    Because static collections behave much more predictably than live collections, and because NodeLists have a `forEach` method, I've gotten into the habit of always using `querySelectorAll` to select elements, when possible, because it returns a static NodeList. (qSA is much more flexible than any of the other methods, too) – CertainPerformance Feb 06 '20 at 08:11