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

Tom*_*Tom 343 javascript arrays object

有没有更有效的方法将HTMLCollection转换为数组,除了迭代所述集合的内容并手动将每个项目推入数组?

har*_*rpo 612

var arr = Array.prototype.slice.call( htmlCollection )
Run Code Online (Sandbox Code Playgroud)

将使用"本机"代码具有相同的效果.

编辑

由于这得到了很多的意见,说明(每@奥里奥尔的评论),下面的更简洁的表达是有效等价的:

var arr = [].slice.call(htmlCollection);
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

var arr = Array.from(htmlCollection);
Run Code Online (Sandbox Code Playgroud)

编辑

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

var arr = [...htmlCollection];
Run Code Online (Sandbox Code Playgroud)

我已经确认上述两种方法都有效NodeList.

  • 快捷方式`[] .slice.call(htmlCollection)`也可以. (29认同)
  • 这在IE6中失败了. (7认同)
  • [不起作用](http://jsfiddle.net/P7j98/)到Internet Explorer**8**. (6认同)
  • Typescript 不允许展开运算符,因为 htmlCollection 没有 `[Symbol.iterator]()` 方法。 (5认同)
  • [] .slice快捷方式不等效,因为它还会创建未使用的空数组实例.但是不确定编译器是否能够优化它. (3认同)
  • IE11不支持`Array.from`,即`from`. (2认同)

mid*_*ido 79

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

let arry = [...htmlCollection] 
Run Code Online (Sandbox Code Playgroud)

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

let arry = Array.from(htmlCollection)
Run Code Online (Sandbox Code Playgroud)

  • 另外,ES6添加了`Array.from()` (9认同)
  • 注意第一个,当使用babel进行转换时会有一个微妙的错误,其中[... htmlCollection]将返回一个带有htmlCollection的数组,因为它是唯一的元素. (4认同)
  • 数组传播运算符不适用于htmlCollection。它仅适用于NodeList。 (3认同)

Cod*_*ith 20

我看到了一种更简洁的方法来获取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
}
Run Code Online (Sandbox Code Playgroud)

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


Gar*_*vis 6

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

从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;
}
Run Code Online (Sandbox Code Playgroud)

Array.prototype.slice可能不会使用,因为它不是每个浏览器都可用.我担心性能非常糟糕,因为有一个回退是一个javascript循环iterable.

  • OP要求的另一种方式是"迭代所述集合的内容并手动将每个项目推入数组",但这正是`$ A`函数在大多数情况下的作用. (2认同)

Nic*_*las 5

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

var arr = [];
[].push.apply(arr, htmlCollection);
Run Code Online (Sandbox Code Playgroud)

由于jsperf目前还处于宕机状态,这里有一个jsfiddle比较了不同方法的性能。https://jsfiddle.net/qw9qf48j/


Sha*_*ani 5

要以有效的方式将类数组转换为数组,我们可以使用jQuery makeArray

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

用法:

var domArray = jQuery.makeArray(htmlCollection);
Run Code Online (Sandbox Code Playgroud)

一点额外的:

如果您不想保留对数组对象的引用(大多数情况下 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.
}
Run Code Online (Sandbox Code Playgroud)

什么是类数组?

HTMLCollection是一个"array-like"对象,类数组对象类似于数组的对象,但缺少很多功能定义:

类数组对象看起来像数组。它们具有各种编号元素和长度属性。但这就是相似性停止的地方。类似数组的对象没有任何 Array 的函数,而且 for-in 循环甚至不起作用!


Rom*_*din 5

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

alert(
    Array.prototype.reduce.call(
        document.querySelector('ol').children,
        (acc, { textContent }, i) => `${acc}${i + 1}) ${textContent}` + `\n`,
        '',
    ),
);
Run Code Online (Sandbox Code Playgroud)
<ol>
    <li>foo</li>
    <li>bar</li>
    <li>bat</li>
    <li>baz</li>
</ol>
Run Code Online (Sandbox Code Playgroud)