Skip to content

Instantly share code, notes, and snippets.

@minitech
Created May 19, 2012 22:52
Show Gist options
  • Save minitech/2732683 to your computer and use it in GitHub Desktop.
Save minitech/2732683 to your computer and use it in GitHub Desktop.
Why you should use my new way to convert to an array
// The data
var items = document.getElementsByTagName('p');
// The old way
var arr = Array.prototype.slice.call(items);
// Pros:
// - Doesn't need a helper method that loops through stuff
//
// Cons:
// - Verbose
// - Doesn't work in IE 8 or lower
// The new way
var arr = Array.apply([], items);
// Pros:
// - Doesn't need a helper method that loops through stuff
// - Reasonably concise
// - Works in IE 7 and 8 at least
//
// Cons:
// - None that I can think of! Take that, old way! (jsPerf test pending.)
// Awesome new way brought to you by Ryan O'Hara (minitech)
@pimvdb
Copy link

pimvdb commented May 20, 2012

A quick note: don't use this on arguments.

(function() { return Array.apply([], arguments); })(2);

will return a sparse array of length 2. (NodeLists won't have this issue, though.)

Also, you don't actually have to pass an array as the this value there. null works too.

And the verbosity of the "old way" can be easily solved with an alias, and browser compatibility with a shim. I do think the "old way" is not bad at all. :-)

@florian
Copy link

florian commented May 20, 2012

@pimvdb This doesn't have anything to do with arguments I think, it's just the way Array works.

Array(1, 2); // [1, 2]
Array(1); // [,] – Returns an array with the length of one, not [1]
// To make this more clear:
Array(5).length; // 5 – not 1 as you might expect.

Pretty weird, but it can be useful in a few situations (underscore.js makes use of it).


Are you sure the old way doesn't work in IE? Unfortunately I'm not able test it on Linux.

@pimvdb
Copy link

pimvdb commented May 20, 2012

@js-coder: That's what I meant. For NodeLists the behaviour of Array does not matter because they never consist of a number, but for arguments it does matter in case you pass a number as the only argument to the function.

Array.prototype.slice throws an error complaining about the type of this in IE8.

@florian
Copy link

florian commented May 20, 2012

@pimvdb Oh, that's true. Array.apply([], document.getElementById('id')) returns an empty array for me though.
I expected it to return an array containing the DOM node.

Edit: Array.prototype.slice.call(document.getElementById('id')) returns an empty array, too.

@pimvdb
Copy link

pimvdb commented May 20, 2012

@js-coder: .apply expects an array, so:

Array.apply([], [ document.getElementById('id') ]);

But since getElementById returns at most one element, the whole .apply trick is not necessary I think. You could just do [ elem ] to put the element in an array. As I understand it, the gist is about converting an array-like object to a real array, which is a problem you don't encounter with getElementById.

@florian
Copy link

florian commented May 20, 2012

@pimvdb Yeah, I had an error in reasoning. :)


[].slice.call(items); seems to work, too, and it's a bit shorter than the usual way. (It creates a new array though, but I don't think you'll see any real performance difference.)

@minitech
Copy link
Author

Argh. Right. And yes, null is better, [] is left over from other experiments.

@js-coder: Still doesn't work in IE, though - that's what I'm trying to fix in a non-frustrating way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment