310

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

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

在我的浏览器上进行基准测试时,我发现它比这慢了 3 倍以上:

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

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

这是我的浏览器(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++]));

EDIT2:我找到了一种更快的方法

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

14 回答 14

296

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

// nl is a NodeList
let myArray = Array.from(nl)
于 2016-03-27T15:19:31.817 回答
227

2021 年更新:nodeList.forEach() 现在是标准的,并且在所有当前浏览器中都受支持(桌面和移动设备上大约 95%)。

所以你可以简单地做:

document.querySelectorAll('img').forEach(highlight);

其他案例

如果您出于某种原因想要将其转换为数组,而不仅仅是迭代它 - 这是一个完全相关的用例 - 您可以使用ES6[...destructuring]Array.from

let array1 = [...mySetOfElements];
// or
let array2 = Array.from(mySetOfElements);

这也适用于不是 NodeLists 的其他类似数组的结构

  • HTMLCollection由例如返回document.getElementsByTagName
  • 具有长度属性和索引元素的对象
  • 可迭代对象(诸如Map和之类的对象Set



过时的 2010 年答案

在某些浏览器中,第二个往往更快,但重点是您必须使用它,因为第一个不是跨浏览器。即使时代变了

@kangax IE 9 预览版

Array.prototype.slice现在可以将某些宿主对象(例如 NodeList's)转换为数组——大多数现代浏览器已经能够做到这一点已经有一段时间了。

例子:

Array.prototype.slice.call(document.childNodes);
于 2010-07-07T23:17:36.683 回答
118

这是使用ES6 扩展运算符的一种新的很酷的方法:

let arr = [...nl];
于 2015-11-20T08:56:13.990 回答
26

在 ES6 中,您可以使用:

  • 数组.from

    let array = Array.from(nodelist)

  • 扩展运算符

    let array = [...nodelist]

于 2019-02-26T11:02:42.270 回答
19

一些优化:

  • 将 NodeList 的长度保存在变量中
  • 在设置之前明确设置新数组的长度。
  • 访问索引,而不是推送或取消移动。

代码(jsPerf):

var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
 arr[i] = nl[i];
}
于 2011-03-09T08:04:35.447 回答
15

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

铬 6:

火狐 3.6:

火狐 4.0b2:

野生动物园 5:

IE9 平台预览版 3:

于 2010-07-07T23:31:58.523 回答
15

最快和跨浏览器是

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

正如我比较

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

*感谢@CMS 的想法!

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

于 2013-02-28T19:43:48.847 回答
8

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

var nodeArray = [].slice.call(nodeList);

看我在这里使用它。

于 2019-08-25T16:02:13.490 回答
7
NodeList.prototype.forEach = Array.prototype.forEach;

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

于 2014-12-25T17:52:33.417 回答
5

更快更短:

// nl is the nodelist
var a=[], l=nl.length>>>0;
for( ; l--; a[l]=nl[l] );
于 2013-01-22T14:11:40.677 回答
3

在这里查看这篇博客文章,讨论同样的事情。据我所知,额外的时间可能与沿着作用域链向上走有关。

于 2010-07-07T23:19:20.343 回答
3

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

function toArray(nl) {
    for(var a=[], l=nl.length; l--; a[l]=nl[l]);
    return a;
}
于 2013-03-08T03:21:33.660 回答
2

以下是截至本文发布之日更新的图表(“未知平台”图表是 Internet Explorer 11.15.16299.0):

Safari 11.1.2 火狐 61.0 铬 68.0.3440.75 Internet Explorer 11.15.16299.0

从这些结果来看,似乎 preallocate 1 方法是最安全的跨浏览器赌注。

于 2018-08-13T15:40:51.470 回答
-3

就这样做吧 vat arr = [...nodeList]

于 2021-05-11T11:02:37.467 回答