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

IT技术 javascript arrays object
2021-02-07 06:16:02

除了遍历所述集合的内容并手动将每个项目推入数组之外,是否有更有效的方法将 HTMLCollection 转换为数组?

6个回答
var arr = Array.prototype.slice.call( htmlCollection )

使用“本机”代码将具有相同的效果。

编辑

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

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

但是请注意@JussiR 的评论,与“详细”形式不同,它确实在此过程中创建了一个空的、未使用的且实际上无法使用的数组实例。编译器对此的处理超出了程序员的知识范围。

编辑

从 ECMAScript 2015 (ES 6) 开始,还有Array.from

var arr = Array.from(htmlCollection);

编辑

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

var arr = [...htmlCollection];

我已经确认上述两项都适用于NodeList.

上述方法的性能比较:http : //jsben.ch/h2IFA

[].slice 快捷方式并不等效,因为它还创建了未使用的空数组实例。不过,不确定编译器是否能够优化它。
2021-03-19 06:16:02
@ChrisNielsen 是的,我被误导了。很抱歉将其传播开来。我没有意识到我在这里也说过。删除了评论以避免混淆,但对于上下文,我在某处读到(或误读)了切片 HTMLCollection 使其行为既像数组又像集合。完全不正确。
2021-03-21 06:16:02
快捷方式[].slice.call(htmlCollection)也有效。
2021-03-28 06:16:02
Fwiw,如果你想散播一点业力大约一个月前@AUTO的回答中也提到了Oriol的评论内容
2021-04-02 06:16:02
Array.from,即fromIE11 不支持。
2021-04-05 06:16:02

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

let arry = [...htmlCollection] 

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

let arry = Array.from(htmlCollection)
注意第一个,使用 babel 进行转换时有一个微妙的错误,其中 [...htmlCollection] 将返回一个带有 htmlCollection 的数组,因为它是唯一的元素。
2021-03-15 06:16:02
此外,ES6 增加了 Array.from()
2021-03-25 06:16:02
基准看起来这两个中的传播运算符更快。
2021-03-26 06:16:02
数组展开运算符不适用于 htmlCollection。它只适用于 NodeList。
2021-03-28 06:16:02
Array.from,即fromIE11 不支持。
2021-04-06 06:16:02

我看到了一种更简洁的获取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。

对于跨浏览器实现,我建议您查看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;
}

它不使用Array.prototype.slice可能是因为它不是在每个浏览器上都可用。恐怕性能很差,因为回退是 .js 文件上的 javascript 循环iterable

我认为我试图提出的观点是没有一个很好的方法来做到这一点,prototype.js 代码表明您可以寻找一个“toArray”方法,但该迭代失败是最安全的路线
2021-03-20 06:16:02
OP 要求采用另一种方式,而不是“遍历所述集合的内容并手动将每个项目推送到数组中”,但这正是该$A函数大部分时间所做的。
2021-03-26 06:16:02
这将在稀疏数组中创建新的未定义成员。在分配之前应该有一个hasOwnProperty测试。
2021-04-04 06:16:02

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

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

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

尝试 var args = (htmlCollection.length === 1 ? [htmlCollection[0]] : Array.apply(null, htmlCollection));
2021-03-13 06:16:02