提问人:Tom 提问时间:10/22/2008 更新时间:3/4/2023 访问量:487786
将 HTMLCollection 转换为数组的最有效方法
Most efficient way to convert an HTMLCollection to an Array
答:
var arr = Array.prototype.slice.call( htmlCollection )
使用“本机”代码将产生相同的效果。
编辑
由于这得到了很多观点,请注意(根据 @oriol 的评论),以下更简洁的表达式实际上是等价的:
var arr = [].slice.call(htmlCollection);
但请注意,根据 @JussiR 的评论,与“冗长”形式不同,它确实在此过程中创建了一个空的、未使用的、实际上不可用的数组实例。编译器对此所做的超出了程序员的权限。
编辑
从 ECMAScript 2015 (ES 6) 开始,还有 Array.from:
var arr = Array.from(htmlCollection);
编辑
ECMAScript 2015 还提供了 spread 运算符,它在功能上等同于(但请注意,它支持映射函数作为第二个参数)。Array.from
Array.from
var arr = [...htmlCollection];
我已经确认上述两者都适用于.NodeList
上述方法的性能比较:http://jsben.ch/h2IFA
评论
[].slice.call(htmlCollection)
Array.from
,即 ,不受 IE11 支持。from
[Symbol.iterator]()
对于跨浏览器实现,我建议您查看原型 .js 函数$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;
}
它不使用可能是因为它不是在每个浏览器上都可用。恐怕性能非常糟糕,因为有一个回退是 javascript 循环。Array.prototype.slice
iterable
评论
$A
这是我个人的解决方案,基于这里的信息(这个线程):
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;
}
如果浏览器支持最好的方式,好的,否则将使用跨浏览器。
评论
[,,]
[undefined, undefined]
我看到了一种更简洁的方法来获取方法,它同样有效。将对象转换为对象的过程如下所示: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。
不确定这是否是最有效的,但简洁的 ES6 语法可能是:
let arry = [...htmlCollection]
编辑:另一个,来自Chris_F评论:
let arry = Array.from(htmlCollection)
评论
Array.from()
Array.from
,即 ,不受 IE11 支持。from
这适用于所有浏览器,包括早期的 IE 版本。
var arr = [];
[].push.apply(arr, htmlCollection);
由于 jsperf 目前仍处于关闭状态,这里有一个比较不同方法性能的 jsfiddle。https://jsfiddle.net/qw9qf48j/
评论
var args = (htmlCollection.length === 1 ? [htmlCollection[0]] : Array.apply(null, htmlCollection));
为了有效地将 array-like 转换为 array,我们可以利用 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"
类似数组的对象看起来像数组。它们有各种编号 元素和 length 属性。但这就是相似性停止的地方。 类数组对象没有任何 Array 的功能,并且 for-in 循环甚至不起作用!
我认为在实例上调用 Array.prototype
函数比将集合转换为数组(例如,或)要好得多,因为在后一种情况下,集合被不必要地隐式迭代并创建了一个新的数组对象,这会占用额外的资源。 迭代函数可以安全地调用具有从 开始的连续数字键的对象,并且具有此类键数量的有效数字值的属性(包括 ,例如,和 的实例),因此这是一种可靠的方法。此外,如果经常需要此类操作,则可以使用空数组来快速访问函数。一个可运行的示例:HTMLCollection
[...collection]
Array.from(collection)
Array.prototype
[0]
length
HTMLCollection
FileList
[]
Array.prototype
alert(
Array.prototype.reduce.call(
document.querySelector('ol').children,
(acc, { textContent }, i) => `${acc}${i + 1}) ${textContent}` + `\n`,
'',
),
);
<ol>
<li>foo</li>
<li>bar</li>
<li>bat</li>
<li>baz</li>
</ol>
有时,即使你以正确的方式编写了代码,但它仍然无法正常工作。
var allbuttons = document.getElementsByTagName("button");
console.log(allbuttons);
var copyAllButtons = [];
for (let i = 0; i < allbuttons.length; i++) {
copyAllButtons.push(allbuttons[i]);
}
console.log(copyAllButtons);
你得到空数组。 喜欢这个
HTMLCollection []
[]
为了解决这个问题,您必须在html文件中的body标签后添加javascript文件的链接。
<script src="./script.js"></script>
正如你在下面看到的,html_file
最终输出
HTMLCollection(6) [button.btn.btn-dark.click-me, button.btn.btn-dark.reset, button#b, button#b, button#b, button#b, b: button#b]
(6) [button.btn.btn-dark.click-me, button.btn.btn-dark.reset, button#b, button#b, button#b, button#b]
我不确定效率,但从纯粹的美学角度来看,我觉得这很令人愉快。
HTMLCollection.prototype.toArray = function() { return Array.from(this); }
现在你可以这样使用它了。
document.getElementsByClassName('tax-status').toArray().forEach(console.log);
上一个:如何从客户端计算机检测当前sharepoint页面?
下一个:接口协定,类对象?
评论
for (var a=[], i=collection.length; i;) a[--i] = collection[i];
Array.prototype.slice.call