问题
Previously answered questions here said that this was the fastest way:
//nl is a NodeList
var arr = Array.prototype.slice.call(nl);
In benchmarking on my browser I have found that it is more than 3 times slower than this:
var arr = [];
for(var i = 0, n; n = nl[i]; ++i) arr.push(n);
They both produce the same output, but I find it hard to believe that my second version is the fastest possible way, especially since people have said otherwise here.
Is this a quirk in my browser (Chromium 6)? Or is there a faster way?
EDIT: For anyone who cares, I settled on the following (which seems to be the fastest in every browser that I tested):
//nl is a NodeList
var l = []; // Will hold the array of Node\'s
for(var i = 0, ll = nl.length; i != ll; l.push(nl[i++]));
EDIT2: I found an even faster way
// nl is the nodelist
var arr = [];
for(var i = nl.length; i--; arr.unshift(nl[i]));
回答1:
The second one tends to be faster in some browsers, but the main point is that you have to use it because the first one is just not cross-browser. Even though The Times They Are a-Changin'
@kangax (IE 9 preview)
Array.prototype.slice can now convert certain host objects (e.g. NodeList’s) to arrays — something that majority of modern browsers have been able to do for quite a while.
Example:
Array.prototype.slice.call(document.childNodes);
回答2:
With ES6, we now have a simple way to create an Array from a NodeList: the Array.from() function.
// nl is a NodeList
let myArray = Array.from(nl)
回答3:
Here's a new cool way to do it using the ES6 spread operator:
let arr = [...nl];
回答4:
Some optimizations:
- save the NodeList's length in a variable
- explicitly set the new array's length before setting.
- access the indices, rather than pushing or unshifting.
Code (jsPerf):
var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
arr[i] = nl[i];
}
回答5:
The results will completely depend on the browser, to give an objective verdict, we have to make some performance tests, here are some results, you can run them here:
Chrome 6:
Firefox 3.6:
Firefox 4.0b2:
Safari 5:
IE9 Platform Preview 3:
回答6:
The most fast and cross browser is
for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);
As I compared in
http://jsbin.com/oqeda/98/edit
*Thanks @CMS for the idea!



回答7:
NodeList.prototype.forEach = Array.prototype.forEach;
Now you can do document.querySelectorAll('div').forEach(function()...)
回答8:
faster and shorter :
// nl is the nodelist
var a=[], l=nl.length>>>0;
for( ; l--; a[l]=nl[l] );
回答9:
In ES6 you can either use:
Array.from
let array = Array.from(nodelist)
Spread operator
let array = [...nodelist]
回答10:
Check out this blog post here that talks about the same thing. From what I gather, the extra time might have to do with walking up the scope chain.
回答11:
This is the function I use in my JS:
function toArray(nl) {
for(var a=[], l=nl.length; l--; a[l]=nl[l]);
return a;
}
回答12:
Here are charts updated as of the date of this posting ("unknown platform" chart is Internet Explorer 11.15.16299.0):




From these results, it seems that the preallocate 1 method is the safest cross-browser bet.
回答13:
Assuming nodeList = document.querySelectorAll("div")
, this is a concise form of converting nodelist
to array.
var nodeArray = [].slice.call(nodeList);
See me use it here.
来源:https://stackoverflow.com/questions/3199588/fastest-way-to-convert-javascript-nodelist-to-array