I have made this code:
var foo=document.createElement("div");
var childs=foo.getElementsByTagName("*");
console.log(childs.length);//0 OK
var a=document.createElement("a");
foo.appendChild(a);
console.log(childs.length);//1 WTF?
A fiddle: http://jsfiddle.net/RL54Z/3/
I don’t have to write childs=foo.getElementsByTagName("*"); between the fifth and the sixth line so that childs.length is updated.
How can it be?
Most lists of nodes in the DOM (e.g. returned from
getElementsBy*,querySelectorAll, andNode.childNodes) are not simple Arrays but ratherNodeListobjects.NodeListobjects are usually “live”, in that changes to the document are automatically propagated to theNodelistobject. (An exception is the result fromquerySelectorAll, which is not live!)So as you can see in your example, if you retrieve a NodeList of all
aelements, then add anotheraelement to the document, thatawill appear in your NodeList object.This is why it is unsafe to iterate through a NodeList while making changes to the document at the same time. E.g., this code will behave in surprising ways:
What will happen is you will end up skipping elements! Either iterate backwards from the end of the NodeList, or copy the NodeList to a plain Array (which will not update) and then work with that.
Read more about NodeLists at the Mozilla MDC site.