Today I found out something interesting about getElementsByTagName. This method is quite popular, it returns all elements of a requested tag under a specific parent element.

The type which is returned out of a getElementsByTagName call is NodeList, which is not exactly an Array, but is enumerable and has the length property.

When you call document.getElementsByTagName(“div”) you get a NodeList of all div tags, but it seems that every time you use this variable, it shows an up to date list.

Meaning - if you have a NodeList instance of all divs on the document and then you dynamically add more divs to the document, this instance will contain all the new divs as well. Same for removed divs.

Test Case:

“`html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

```js

var divs=document.getElementsByTagName("div");

console.log("divs.length="+divs.length); // 4

document.body.appendChild(document.createElement("div"));
document.body.appendChild(document.createElement("div"));
document.body.appendChild(document.createElement("div"));

console.log("divs.length="+divs.length); // 7

document.body.removeChild(divs[0]);

console.log("divs.length="+divs.length); // 6

[iframe: style=“width: 100%; height: 310px” src=“http://jsfiddle.net/xUsVn/embedded/js,html,result”]

How to Maintain the Original Collection?

Simply, by creating a new Array out of the NodeList’s contents:

1
2
3
4
5
6
var divs=document.getElementsByTagName("div");
divs=Array.prototype.slice.call(divs);
// the above is a shortcut to:
// var tmp=[];
// for (var i=0,l=divs.length;i<l;i++) tmp.push(divs[i]);
// divs=tmp;

MooTools, jQuery, Prototype etc. do not return a NodeList out of their DOM selector engines. They return an Array instance, so no need to worry about this.

This also applies to getElementsByClassName and getElementsByName, but not to querySelectorAll.

I investigated a bit inside the WebKit’s source and it seems like that the getElementsByTagName / getElementsByClassName / getElementsByName methods return a DynamicNodeList while the querySelectorAll method returns StaticNodeList.