将HTMLCollection转换为数组的最有效方法

时间:2008-10-21 18:04:54

标签: javascript arrays object

是否有更有效的方法将HTMLCollection转换为数组,而不是遍历所述集合的内容并手动将每个项目推送到数组中?

8 个答案:

答案 0 :(得分:533)

var arr = Array.prototype.slice.call( htmlCollection )

使用“原生”代码具有相同的效果。

修改

由于这会获得大量观点,请注意(根据@ oriol的评论)以下更简洁的表达式有效等效:

var arr = [].slice.call(htmlCollection);

但请注意@ JussiR的评论,与“详细”形式不同,它确实在此过程中创建了一个空的,未使用的,实际上无法使用的数组实例。编译器对此做了什么是在程序员的肯定之外。

修改

自ECMAScript 2015(第6版)以来,还有Array.from

var arr = Array.from(htmlCollection);

修改

ECMAScript 2015还提供了spread operator,它在功能上等同于Array.from(尽管注意Array.from支持映射函数作为第二个参数)。

var arr = [...htmlCollection];

我已经确认上述两项工作都在NodeList

答案 1 :(得分:76)

不确定这是否是最有效的,但简洁的ES6语法可能是:

let arry = [...htmlCollection] 

编辑:另一个,来自Chris_F评论:

let arry = Array.from(htmlCollection)

答案 2 :(得分:19)

我看到一种更简洁的方法来获取Array.prototype方法,这种方法同样有效。将HTMLCollection对象转换为Array对象如下所示:

[].slice.call( yourHTMLCollectionObject );

并且,正如评论中所提到的,对于IE7及更早版本等旧版浏览器,您只需使用兼容性功能,例如:

function toArray(x) {
    for(var i = 0, a = []; i < x.length; i++)
        a.push(x[i]);

    return a
}

我知道这是一个老问题,但我觉得接受的答案有点不完整;所以我以为我会把它扔到那里FWIW。

答案 3 :(得分:6)

对于跨浏览器的实现,我建议您查看prototype.js $A函数

copyed from 1.6.1

function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

它可能不会使用Array.prototype.slice,因为它并非在每个浏览器上都可用。我担心性能非常糟糕,因为后退是iterable上的javascript循环。

答案 4 :(得分:3)

这是我的个人解决方案,基于此处的信息(此主题):

var Divs = new Array();    
var Elemns = document.getElementsByClassName("divisao");
    try {
        Divs = Elemns.prototype.slice.call(Elemns);
    } catch(e) {
        Divs = $A(Elemns);
    }

Gareth Davis在他的帖子中描述了$ A:

function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

如果浏览器支持最佳方式,那么,否则将使用跨浏览器。

答案 5 :(得分:3)

这适用于所有浏览器,包括早期的IE版本。

var arr = [];
[].push.apply(arr, htmlCollection);

由于jsperf目前仍然处于关闭状态,因此这里有一个比较不同方法性能的jsfiddle。 https://jsfiddle.net/qw9qf48j/

答案 6 :(得分:1)

要高效地将类似数组的数组转换为数组,我们可以使用jQuery makeArray

  

makeArray:将类似数组的对象转换为真正的JavaScript数组。

用法:

var domArray = jQuery.makeArray(htmlCollection);

一些额外的内容:

如果您不想保留对数组对象的引用(大多数情况下HTMLCollections是动态更改的,因此最好将它们复制到另一个数组中,此示例将密切关注性能:

var domDataLength = domData.length //Better performance, no need to calculate every iteration the domArray length
var resultArray = new Array(domDataLength) // Since we know the length its improves the performance to declare the result array from the beginning.

for (var i = 0 ; i < domDataLength ; i++) {
    resultArray[i] = domArray[i]; //Since we already declared the resultArray we can not make use of the more expensive push method.
}

什么是类似数组的?

HTMLCollection"array-like"对象,array-like对象与数组的对象相似,但是缺少许多功能定义:

  

类似数组的对象看起来像数组。他们有各种编号   元素和length属性。但这就是相似的地方。   类似数组的对象没有任何数组功能,并且   循环甚至不起作用!

答案 7 :(得分:0)

我认为在 Array.prototype 的实例上调用 HTMLCollection 函数比将集合转换为数组(例如,[...collection] 或 {{1 }}),因为在后一种情况下,一个集合被不必要地隐式迭代并创建了一个新的数组对象,这会消耗额外的资源。 Array.from(collection) 迭代函数可以安全地调用具有从 Array.prototype 开始的连续数字键和具有此类键数量的有效数值的 [0] 属性的对象(包括例如 { {1}} 和 length),所以这是一种可靠的方式。另外,如果此类操作经常需要,可以使用空数组HTMLCollection来快速访问FileList函数;或者可以创建 [] 的快捷方式。一个可运行的例子:

Array.prototype
Array.prototype