-
-
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 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.
@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. (
NodeLists won't have this issue, though.)Also, you don't actually have to pass an array as the
thisvalue there.nullworks 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. :-)