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

jai*_*s89 241 javascript arrays nodelist

以前回答的问题说这是最快的方式:

//nl is a NodeList
var arr = Array.prototype.slice.call(nl);
Run Code Online (Sandbox Code Playgroud)

在我的浏览器基准测试中,我发现它比这慢3倍:

var arr = [];
for(var i = 0, n; n = nl[i]; ++i) arr.push(n);
Run Code Online (Sandbox Code Playgroud)

它们都产生相同的输出,但我发现很难相信我的第二个版本是最快的方式,特别是因为人们在这里说了不同的.

这是我浏览器中的怪癖(Chromium 6)吗?或者有更快的方法吗?

编辑:对于任何关心的人,我选择了以下内容(这似乎是我测试的每个浏览器中最快的):

//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++]));
Run Code Online (Sandbox Code Playgroud)

EDIT2:我发现了一种更快的方法

// nl is the nodelist
var arr = [];
for(var i = nl.length; i--; arr.unshift(nl[i]));
Run Code Online (Sandbox Code Playgroud)

web*_*dif 201

使用ES6,我们现在有一种从NodeList创建数组的简单方法:该Array.from()函数.

// nl is a NodeList
let myArray = Array.from(nl)
Run Code Online (Sandbox Code Playgroud)

  • @ user5508297比切片调用技巧更好.比for循环慢,但这并不是我们可能想要一个没有遍历它的数组.语法美观,简单,易记! (8认同)
  • Array.from 的好处是您可以使用映射参数: `console.log(Array.from([1, 2, 3], x => x + x)); // 预期输出:数组 [2, 4, 6]` (2认同)

gbl*_*zex 191

第二个在某些浏览器中往往更快,但主要的一点是你必须使用它,因为第一个不是跨浏览器.尽管"泰晤士报他们是一个长安"

@kangax( IE 9预览)

Array.prototype.slice现在可以将某些主机对象(例如NodeList)转换为数组 - 大多数现代浏览器已经能够做很长一段时间了.

例:

Array.prototype.slice.call(document.childNodes);
Run Code Online (Sandbox Code Playgroud)

  • 因为NodeLists不是语言的一部分,所以它们是DOM API的一部分,众所周知,它是错误的/不可预测的,尤其是在IE中 (8认同)
  • 但它们不能用于IE中的NodeLists(我知道它很糟糕,但是嘿看到我的更新) (5认同)
  • 如果您在帐户中使用IE8,则Array.prototype.slice不是跨浏览器. (3认同)

Ale*_*son 98

以下是使用ES6扩展运算符执行此操作的新方法:

let arr = [...nl];
Run Code Online (Sandbox Code Playgroud)

  • 打字稿中没有为我工作.`ERROR TypeError:el.querySelectorAll(...).slice不是函数` (5认同)

Tha*_*hai 19

一些优化:

  • 将NodeList的长度保存在变量中
  • 在设置之前显式设置新数组的长度.
  • 访问指数,而不是推或不推.

代码(jsPerf):

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


CMS*_*CMS 15

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

Chrome 6:

Firefox 3.6:

Firefox 4.0b2:

Safari 5:

IE9平台预览版3:


Fel*_*oni 14

最快速和跨浏览器是

for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);
Run Code Online (Sandbox Code Playgroud)

正如我在比较中

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

*感谢@CMS的想法!

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


Joh*_*ams 7

NodeList.prototype.forEach = Array.prototype.forEach;
Run Code Online (Sandbox Code Playgroud)

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

  • 不要使用Object.prototype:它打破了JQuery和一些像字典文字语法这样的东西. (2认同)

小智 5

更快更短:

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

  • 此外,这是错误的.当`l`为'0`时,循环结束,因此不会复制`0'元素(记住索引'0'处有一个元素) (5认同)
  • 为什么`>>> 0`?为什么不把赋值放在for循环的第一部分? (3认同)

Isa*_*lla 5

在ES6中,您可以使用:

  • Array.from

    let array = Array.from(nodelist)

  • 点差运算符

    let array = [...nodelist]

  • 不添加任何新的内容已经在以前的答案中写过。 (3认同)

Udo*_* E. 5

假设nodeList = document.querySelectorAll("div"),这是转换nodelist为数组的简洁形式。

var nodeArray = [].slice.call(nodeList);
Run Code Online (Sandbox Code Playgroud)

看我在这里使用它。