让我们看看一些迭代 NodeList
的选项,就像你从运行 document.querySelectorAll
后获得的那样。
我们已经撰写了一篇关于此的更新文章:循环遍历 querySelectorAll NodeLists 的多种选项。
并非所有浏览器都支持 NodeList 上的 forEach,但对于那些支持的浏览器
buttons.forEach((button) => {
button.addEventListener('click', () => {
console.log("forEach worked");
});
});
这是一个巧妙的方法,可以通过更深层次的浏览器支持来解决这个问题。
var divs = document.querySelectorAll('div');
[].forEach.call(divs, function(div) {
// do whatever
div.style.color = "red";
});
公平警告,Todd Motto 解释了为什么这种方法相当hacky,详细说明了它超过10个问题。
你也可以使用传统的 for 循环
var divs = document.querySelectorAll('div'), i;
for (i = 0; i < divs.length; ++i) {
divs[i].style.color = "green";
}
Todd 的建议是自己编写一个方法
// forEach method, could be shipped as part of an Object Literal/Module
var forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]); // passes back stuff we need
}
};
// Usage:
// optionally change the scope as final parameter too, like ECMA5
var myNodeList = document.querySelectorAll('li');
forEach(myNodeList, function (index, value) {
console.log(index, value); // passes index + value back!
});
你也可以自己展开列表,这样你就可以在使用过程中访问其他数组方法。
[...buttons].forEach((button) => {
button.addEventListener('click', () => {
console.log("spread forEach worked");
});
});
还有 for...of 循环。Firefox 是第一个支持此功能的浏览器,但支持度已经相当不错了
for (const button of buttons) {
button.addEventListener('click', () => {
console.log("for .. of worked");
});
}
这非常复杂(可能很危险,不建议),但你可以 创建 NodeList 并使其具有与 Array 相同的 forEach 函数,然后使用它。
NodeList.prototype.forEach = Array.prototype.forEach;
var divs = document.querySelectorAll('div').forEach(function(el) {
el.style.color = "orange";
})
在 MDN 文章 中有更多信息。
执行最后一个版本并接管 Array 方法的更安全的方法是执行以下操作
当然,如果你要针对旧版浏览器,你仍然需要确保你有一个 Array.forEach 的 polyfill。
请注意,有些人 不鼓励使用
[].forEach.call(..)
模式,而是更倾向于经典循环。嘿,这为我节省了一些时间——我很好奇为什么我不能用 forEach 循环。谢谢!
有一个非常好的函数可以为你提供一个数组
function getDomNodeArray(selector) {
// 将元素作为 DOM 集合获取
var elemCollection = document.querySelectorAll(selector);
// 将 DOM 集合强制转换为数组
var elemArray = Array.prototype.slice.apply(elemCollection);
return elemArray;
};
这正是我所使用的。我使用了额外的可选参数,即“上下文”或调用 querySelectorAll() 的元素(默认为 document)
然后用法可能是
等等……它非常强大,却又非常简单。它还有一个单行形式
我只是想分享这个“发现”……。
使用展开运算符的 ES2015 变体
这是我的偏好。
如果你正在使用 ES6,你应该也可以这样做
Array.from(querySelectorAll('img')).forEach(img => doStuff);
简洁明了。
聪明。
简洁明了且优雅。
只想说明
.from
目前不支持 Internet Explorer——MDN重载 NodeList,然后就没有头痛了 :)
这应该是最快的方法
nl 等于 NodeLIst
一种不同的方法,稍微更直接一些
(已测试。)
你也可以这样做
或者你可以只使用
Array.from
https://mdn.org.cn/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from然后它实际上将成为一个数组。
这个怎么样
我刚刚注意到
NodeList.prototype.forEach()
显然现在是 Chrome 和 Firefox 中官方 JS-API 的一部分。有关详细信息和官方 polyfill,请参阅 https://mdn.org.cn/en-US/docs/Web/API/NodeList/forEach。现在我们也有 Array.from() 了 :)
因此,我进行了一些测试以查看这些建议的效果如何,得出的结论是,循环遍历节点列表最快的方法(执行时间)是只使用 Array.prototype.forEach.call… Todd 的解决方案在执行包含 10000 个项目的空节点列表时花费了 7.9 毫秒,而原生解决方案在相同的节点列表上花费了 0.08 毫秒……因此,我建议 Todd 和你们不要自己编写方法来循环遍历节点列表