JavaScript Quirks – Array Slicing Node Lists

For a while many developers, including myself, suggested that Array.prototype.slice() be used to turn any array-like object into an array. Recently, I was alerted to a scenario in which this does not work as expected. Let’s take the following code for example:

var elems = document.body.getElementsByTagName('*');
var arrElems = Array.prototype.slice.call(elems, 0);

In most browsers, the above code would take the node list assigned to elems and create an array of those nodes and assign it to arrElems. Leave it to Internet Explorer to be the exception, right? Unfortunately, Internet Explorer 8 and lower throw a run-time error: JScript object expected.

For that reason, functions that are written to reliably turn array-like objects into arrays should use the good old-fashioned loop in order to accomplish the task:

function makeArray(o) {
  for (var i = 0, l = o.length, a = new Array(i); i < l; i++) {
    if (i in o) {
      a[i] = o[i];
    }
  }
  return a;
}

As you will notice, the above function creates an array of the same length and only adds the values where found (just as slice() does when copying arrays).

It might be argued that using hasOwnProperty() is a faster solution, but after doing this performance test it seems that the fastest implementation depends on the browser. On the other hand, going in reverse order seemed generally slightly slower. Therefore, I decided to settle with the above implementation which can be finely tuned depending on the target environment. Of course, you could use slice() and then if it fails, fall back to the for loop:

function makeArray(o) {
  try {
    return Array.prototype.slice.call(o);
  } catch (e) {}
  
  for (var i = 0, l = o.length, a = new Array(i); i < l; i++) {
    if (i in o) {
      a[i] = o[i];
    }
  }
  return a;
}

The aforementioned performance test shows that this solution is actually one of the more performant solutions across browsers. In the end it is all up to you. Have fun! :cool:

Leave a Reply

Your email address will not be published. Required fields are marked *


8 − six =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">