将JavaScript NodeList转换为数组最快的方法?

以前在这里回答的问题说这是最快的方法:

//nl is a NodeList var arr = Array.prototype.slice.call(nl); 

在我的浏览器基准testing中,我发现它比这慢了3倍多:

 var arr = []; for(var i = 0, n; n = nl[i]; ++i) arr.push(n); 

他们都产出相同的产出,但我很难相信我的第二个版本是最快的方式,特别是因为人们在这里说的其他。

这是我的浏览器(铬6)怪癖? 还是有更快的方法?

编辑:任何关心的人,我解决以下(这似乎是我testing的每个浏览器中最快):

 //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++])); 

编辑2:我发现一个更快的方法

 // nl is the nodelist var arr = []; for(var i = nl.length; i--; arr.unshift(nl[i])); 

第二个在一些浏览器中往往会更快,但是最重要的是你必须使用它,因为第一个浏览器不是跨浏览器的。 即使他们是一个长安'

@kangaxIE 9预览

Array.prototype.slice现在可以将某些主机对象(例如NodeList的)转换为数组,这是现代浏览器大部分已经能够完成的事情。

例:

 Array.prototype.slice.call(document.childNodes); 

有了ES6,我们现在有一个简单的方法来从NodeList创build一个数组:

 // nl is a NodeList let myArray = Array.from(nl) 

下面是一个使用ES6扩展运算符的新方法:

 let arr = [...nl]; 

一些优化:

  • 将NodeList的长度保存在一个variables中
  • 在设置之前明确设置新arrays的长度。
  • 访问指数,而不是推或不移。

代码( jsPerf ):

 var arr = []; for (var i = 0, ref = arr.length = nl.length; i < ref; i++) { arr[i] = nl[i]; } 

结果将完全取决于浏览器,给出一个客观的判断,我们必须做一些性能testing,这里有一些结果,你可以在这里运行它们:

Chrome 6:

Firefox 3.6:

Firefox 4.0b2:

Safari 5:

IE9平台预览3:

最快和跨浏览器是

 for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]); 

正如我在比较

http://jsbin.com/oqeda/98/edit

*感谢@CMS的想法!

铬(类似谷歌浏览器)火狐歌剧

 NodeList.prototype.forEach = Array.prototype.forEach; 

现在你可以做document.querySelectorAll('div')。forEach(function()…)

越来越快:

 // nl is the nodelist var a=[], l=nl.length>>>0; for( ; l--; a[l]=nl[l] ); 

看看这里的博客文章,谈论同样的事情。 从我所收集到的信息来看,额外的时间可能与走上范围链有关。

这是我在JS中使用的函数:

 function toArray(nl) { for(var a=[], l=nl.length; l--; a[l]=nl[l]); return a; } 

只是在这里成为一名完成者,而且这些人很快打字:

 let arr1 = Array.prototype.filter.call(nl, n => true); let arr2 = Array.prototype.map.call(nl, n => n);