Question

What could be the problem with reversing the array of DOM objects as in the following code:

var imagesArr = new Array();
imagesArr = document.getElementById("myDivHolderId").getElementsByTagName("img");
imagesArr.reverse();

In Firefox 3, when I call the reverse() method the script stops executing and shows the following error in the console of the Web Developer Toolbar:

imagesArr.reverse is not a function

The imagesArr variable can be iterated through with a for loop and elements like imagesArr[i] can be accessed, so why is it not seen as an array when calling the reverse() method?

Was it helpful?

Solution

Because getElementsByTag name actually returns a NodeList structure. It has similar array like indexing properties for syntactic convenience, but it is not an array. For example, the set of entries is actually constantly being dynamically updated - if you add a new img tag under myDivHolderId, it will automatically appear in imagesArr.

See http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-536297177 for more.

OTHER TIPS

getElementsByTag() returns a NodeList instead of an Array. You can convert a NodeList to an Array but note that the array will be another object, so reversing it will not affect the DOM nodes position.

var listNodes = document.getElementById("myDivHolderId").getElementsByTagName("img");
var arrayNodes = Array.slice.call(listNodes, 0);
arrayNodes.reverse();

In order to change the position, you will have to remove the DOM nodes and add them all again at the right position.

Array.prototype.slice.call(arrayLike, 0) is a great way to convert an array-like to an array, but if you are using a JavaScript library, it may actually provide a even better/faster way to do it. For example, jQuery has $.makeArray(arrayLike).

You can also use the Array methods directly on the NodeList:

Array.prototype.reverse.call(listNodes);

getElementsByTag() returns a NodeList instead of an Array. You need to convert the NodeList to an array then reverse it.

var imagesArr = [].slice.call(document.getElementById("myDivHolderId").getElementsByTagName("img"), 0).reverse();

I know this question is old but I think it needs a bit of clarification as some of the answers here are outdated as W3C changed the definition, and consequently the return value of these methods getElementsByTagName() and getElementsByClassName()

These methods as of the time of writing this answer return an object - empty or not - of type HTMLCollection and not NodeList.

It's like the difference between the properties children which returns an object of type HTMLCollection since it's only composed of elements and excluding text or comment nodes, and childNodes which returns an object of type NodeList since it could contain other node types like text and comments as well.

Note: I'd go on tangent here and express my lack of insight on why querySelectorAll() method currently returns a NodeList and not an HTMLCollection since it exclusively works on element nodes in the document and nothing else.

Probably it has something to do with potential coverage of other node types in the future and they went for a more future proof solution, who knows really? :)

EDIT: I think I got the rationale behind this decision to opt for a NodeList and not an HTMLCollection for the querySelectorAll().

Since they constructed HTMLCollection to be exclusively and entirely live and since this method doesn't need this live functionality, they decided for a NodeList implementation instead to best serve its purpose economically and efficiently.

Your first line is irrelevant, since it doesn't coerce the assignment to the variable, javascript works the other way. imagesArr, is not of Type Array(), its of whatever the return type of getElementsByTagName("img") is. In this case, its an HtmlCollection in Firefox 3.

The only methods on this object, are the indexers, and length. In order to work in reverse, just iterate backwards.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top