将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]));
第二个在一些浏览器中往往会更快,但是最重要的是你必须使用它,因为第一个浏览器不是跨浏览器的。 即使他们是一个长安'
@kangax ( IE 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);