34

I'm not sure my current implementation is available all the time:

function isNodeList(nodes) {
    var result = Object.prototype.toString.call(nodes);
    // modern browser such as IE9 / firefox / chrome etc.
    if (result === '[object HTMLCollection]' || result === '[object NodeList]') {
        return true;
    }
    //ie 6/7/8
    if (typeof(nodes) != 'object') {
        return false;
    }
    // detect length and item 
    if (!('length' in nodes) || !('item' in nodes)) {
        return false;
    }
    // use the trick NodeList(index),all browsers support
    try {
        if (nodes(0) === null || (nodes(0) && nodes(0).tagName)) return true;
    }
    catch (e) {
        return false;
    }
    return false;
}

A common situation is {length:1,item:function(){return [];}}
The value of result in chrome / safari / opera is '[object NodeList]'.
In firefox and IE 9 , it is '[object HTMLCollection]'.

Which is the standard value?

Piper
  • 1,266
  • 3
  • 15
  • 26
simon xu
  • 954
  • 2
  • 10
  • 19
  • 1
    [How to check if an object is an instance of a NodeList in IE?](http://stackoverflow.com/questions/151348/how-to-check-if-an-object-is-an-instance-of-a-nodelist-in-ie) – Matt Ball Aug 30 '11 at 02:58
  • @Matt Ball -- typeof nodes.item returns 'string' in ie6,not 'function'.so we need more detection. – simon xu Aug 30 '11 at 03:11

7 Answers7

51

The following should return true, if nodes is of type NodeList

NodeList.prototype.isPrototypeOf(nodes)

@DavidSpector, for HTMLCollection you can similarly use :

HTMLCollection.prototype.isPrototypeOf(collection)
vineethbc
  • 858
  • 10
  • 15
25

I would structure the code differently:

function isNodeList(nodes) {
    var stringRepr = Object.prototype.toString.call(nodes);

    return typeof nodes === 'object' &&
        /^\[object (HTMLCollection|NodeList|Object)\]$/.test(stringRepr) &&
        (typeof nodes.length === 'number') &&
        (nodes.length === 0 || (typeof nodes[0] === "object" && nodes[0].nodeType > 0));
}

Notes:

  • less return paths make easier-to-read code
  • stick with one type of logic, if possible (i.e. use less negated checks)
  • "item" is not mandatorily in a nodeList
  • use hasOwnProperty() instead of in
  • use square brackets to index into the list
  • I don't think a try/catch is really necessary, but that might be wrong - you decide
  • check for nodeType instead of tagName, as text nodes or comments do not have a name
  • add more checks to the && chain if you see fit
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • occasionally getting this error live: `'0.nodeType' is null or not an object` . any idea what could have slipped through? – tester Apr 24 '12 at 23:42
  • 1
    why even have the return true/false… just return the value you're testing in the if. i.e. remove the if statement + returns and just replace it with return. – timoxley Nov 01 '12 at 19:01
  • 2
    `nodes.hasOwnProperty('length')` returning false in Chrome for me. maybe `typeof nodes.length === 'number'` is better? – Max G J Panas Dec 21 '15 at 16:02
  • 1
    @MaxGJPanas Yes, that worked at the time, but apparently things change. I've modified my answer accordingly, thanks for the heads-up. – Tomalak Dec 22 '15 at 10:06
16

Here is how to test if an object is a NodeList in modern browsers:

if (nodes instanceof NodeList) {
  // It's a NodeList object
}
rosell.dk
  • 2,228
  • 25
  • 15
13

script:

Element.prototype.isNodeList = function() {return false;}
NodeList.prototype.isNodeList = HTMLCollection.prototype.isNodeList = function(){return true;}

use like this:

var d; // HTMLCollection|NodeList|Element
if(d.isNodeList()){
  /*
    it is HTMLCollection or NodeList
    write your code here
  */
}else{
  /*
    it is not HTMLCollection and NodeList
    write your code here
  */
}
Guja1501
  • 999
  • 7
  • 16
11

Check if variable is an HTMLcollection or a dom element

  var foo = document.getElementById('mydiv');
  var foo2 = document.getElementsByClassName('divCollection');
  console.log(foo instanceof HTMLElement);
  console.log(foo instanceof HTMLCollection);
Community
  • 1
  • 1
koech
  • 566
  • 1
  • 5
  • 15
  • @Horay I hope this helps. – koech Nov 07 '16 at 04:49
  • Thanks! Yes it does help! How can I check if it's not `instanceof HTMLCollection`? Where do I put the (!) exclamation mark? – Horay Nov 07 '16 at 20:01
  • The good solution... thanks. @Horay Probably it's too late, but... if (!(stuff instanceof That)) { ... } – eglaf Mar 02 '17 at 10:15
  • It's actually `foo instanceof window.HTMLCollection` if you use the standard style - https://standardjs.com/ –  Jan 06 '20 at 14:27
5

This answer is probably really really late, but....

if (nodes == '[object NodeList]') {
  // It's a nodeList
}
Mohamed Moustafa
  • 279
  • 4
  • 11
0

I created a benchmark of all answers here to see, what is the best approve in speed. Turns out NodeList.prototype.isPrototypeOf(nodes) is by far the fastest. But in a normal use-case nodes instanceof NodeList would be fine too.

I personally would just not pick the isNodeList function, because its slow, custom and too much overhead.

eisbehr
  • 12,243
  • 7
  • 38
  • 63