-
-
Save minitech/2732683 to your computer and use it in GitHub Desktop.
// 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 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.
@js-coder: That's what I meant. For NodeList
s 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.
@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.
@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
.
@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.)
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.
A quick note: don't use this on
arguments
.will return a sparse array of length 2. (
NodeList
s 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. :-)