Convert NodeList to array
Asked Answered
S

4

9

I'm having a hard time converting a NodeList to an array in IE 8. The following works perfectly in Chrome, but in IE 8 toArray() is not recognized as valid:

NodeList.prototype.toArray = function() {
    var a = [];

    for (var i = 0, len = this.length; i < len; i++) {
        a[i] = this[i];
    }

    return a;
}

document.all.tags("div").toArray();

I tried adding a prototype function to an array just to check my sanity and it works correctly. That makes me think IE 8 doesn't actually return a NodeList? Here's a full example:

http://jsfiddle.net/e4RbH/

What am I doing wrong?

Sand answered 29/12, 2010 at 21:1 Comment(1)
There is no current standard that says that NodeList has to be a visible and alterable constructor function, or that if there is a constructor function visible as NodeList that it will be used as the return type of all NodeList-returning methods. (After all, a childNodes NodeList and a getElementsByTagName NodeList do very different things.) Prototyping onto the native JS objects is specified by the ECMAScript standard and is reliable; prototyping onto DOM Nodes and other objects not defined by the language standard is unreliable and should be avoided.Downandout
D
3

First, don't use document.all -- it's non-standard and deprecated. Use document.getElementsByTagName to get the DIV elements in your case.

Second, don't extend DOM objects such as NodeList -- built-in objects are a very strange breed and are not required to behave like any other objects that you generally work with. See this article for an in-depth explanation of this: What's wrong with extending the DOM.

Diaphone answered 29/12, 2010 at 21:8 Comment(2)
I was using getElementByTagName, but switched to document.all during testing. This was part of a bigger problem and I tried to simplify it down. The real problem ended up being an extension method to Array which was improperly implemented and affected other code.Sand
Good comments but doesn't answer the questionGuileful
D
11

If you're looking for a modern answer using ES6:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

var nodes = document.querySelectorAll('div');
nodes = Array.from(nodes);
Dishrag answered 8/10, 2017 at 13:12 Comment(1)
You could also use spread operator const array = [...nodes]Vulcanism
T
5

Old question, but here is a tried & true method:

var nodes=document.querySelectorAll("div"); //  returns a node list
nodes=Array.prototype.slice.call(nodes);    //  copies to an array

Explanation

  • document.querySelectorAll uses a CSS-style selector to find elements and returns a node list. It works as of IE 8.
  • The slice method copies a portion of an array-like collection (in this case all of it) into a new array.
  • call allows you to borrow a method from one object to use on another

To find the node list you could also have used `document.getElementsByTagName(), but this one is more flexible.

Triparted answered 22/1, 2017 at 5:18 Comment(1)
You can't call slice on a nodeList in IE8 :\Nighthawk
D
3

First, don't use document.all -- it's non-standard and deprecated. Use document.getElementsByTagName to get the DIV elements in your case.

Second, don't extend DOM objects such as NodeList -- built-in objects are a very strange breed and are not required to behave like any other objects that you generally work with. See this article for an in-depth explanation of this: What's wrong with extending the DOM.

Diaphone answered 29/12, 2010 at 21:8 Comment(2)
I was using getElementByTagName, but switched to document.all during testing. This was part of a bigger problem and I tried to simplify it down. The real problem ended up being an extension method to Array which was improperly implemented and affected other code.Sand
Good comments but doesn't answer the questionGuileful
C
1

IE doesn't support NodeList in the standard way. This is why you should roll your own namespace and NOT extend browser core objects.

You can do alert( typeof window.NodeList ) and see if it's undefined or not.

Covet answered 29/12, 2010 at 21:4 Comment(2)
In Chrome it's function, in IE 8 it's object, not undefined. Either way, this was debugging some old code which I have now refactored into a namespace I already had.Sand
You must have a newer version of IE8 'cause mine is undefined.Covet

© 2022 - 2024 — McMap. All rights reserved.