for 循环 querySelectorAll
Posted
技术标签:
【中文标题】for 循环 querySelectorAll【英文标题】:for of loop querySelectorAll 【发布时间】:2015-08-30 10:11:22 【问题描述】:Mozilla 声明“for of 循环将正确地遍历 NodeList 对象”。 (来源:https://developer.mozilla.org/en-US/docs/Web/API/NodeList)但是,这在 Chrome 43 中不起作用。这是不正确的文档还是浏览器错误?
在带有复选框的页面上使用的复制示例代码:
var list = document.querySelectorAll( 'input[type=checkbox]' );
for (var item of list)
item.checked = true;
【问题讨论】:
我们可以再了解一些上下文吗?你能给我们举个例子吗? 我想知道在 Chrome 中究竟有什么问题。它会引发语法错误吗?它不检查任何复选框吗?for..of
loops 仅支持 implemented as iterators 的对象,其中包含 Symbol.iterator
键/方法。目前,在 Chrome 中,console.log(Symbol.iterator in list); // false
。
@Xufox 它抛出“Uncaught TypeError: undefined is not a function”
【参考方案1】:
编辑:This is shipping in Chrome 51。
Jake Archibald posted a simple fix:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]
And for of 循环。
【讨论】:
同样适用于htmlCollection
等其他人。【参考方案2】:
文档是正确的,但我不会将此称为错误。相反,它是一个“尚未实现的功能”。
这方面没有标准,关于 DOM 应该如何与 ES6 集成的讨论仍然很活跃。请注意,很明显 querySelectorAll
应该返回可以在 for of
循环中使用的可迭代的东西(如常见的期望要求),但不清楚 如何这应该发生(让NodeList
实现Iterable接口?让一些Elements
collection子类Array
?)。
【讨论】:
【参考方案3】:你可以使用Array.from
let _list = document.querySelectorAll('input[type=checkbox]');
let list = Array.from(_list);
for (let item of list)
//... just like an array
item.checked = true
或更多时间
let list = document.querySelectorAll('input[type=checkbox]');
for (let item of Array.from(list))
item.checked = true
重要提示 Array.from
是在 Chrome 45 中引入的 source。
【讨论】:
这样更好吗?每次都需要调用 Array.from。 是的,您确实必须每次都调用Array.from
(并且可能为此包含一个polyfill),但是使用这种方法您并没有尝试扩展DOM。
这与扩展 DOM 有什么关系?【参考方案4】:
由于我在 Gecko 中成功使用 for..of
迭代 NodeList
s,看来这是一个浏览器错误,或者至少是浏览器缺乏。
我目前使用的用户脚本的实际工作代码:
let llnk = document.querySelectorAll("div#threadlist a.threadtitle_unread");
for (let lnk of llnk)
//...
(这也使用let
,但这是另一回事。)
【讨论】:
【参考方案5】:尝试使用Array.prototype.entries()
var list = [].entries.call(document.querySelectorAll("input[type=checkbox]"));
for (item of list)
item[1].checked = true;
;
<input type="checkbox" /><input type="checkbox" />
你也可以使用Array.prototype.values()
var list = [].values.call(document.querySelectorAll("input[type=checkbox]"));
for (item of list)
item.checked = true;
;
<input type="checkbox" /><input type="checkbox" />
【讨论】:
【参考方案6】:这是现代的另一种解决方案:
[...document.querySelectorAll("input[type=checkbox]")].forEach(node =>
node.textContent = "foo";
);
这利用了在 Google Chrome 46+、Firefox 16+ 和 Edge 中受支持的 spread operator,而 arrow function 只是为了好玩。
【讨论】:
重构数组的目的是什么?querySelectorAll
的结果是一个 NodeList,而不是一个数组。通过转换它,我们可以轻松地对其进行迭代。
现在有什么不同?它们都是可迭代的。
正如其他答案所指出的,除非您将 Array 的迭代器分配给 NodeList,否则某些浏览器会给您带来问题(因此您的原始问题)。我只是提供了另一种干净的语法方式来进行forEach
迭代,而不是使用from
或call
。【参考方案7】:
这就是我所做的,换一种方法
Array.prototype.forEach.call(document.querySelectorAll("input[type=checkbox]"),function(ele,idx)
ele.checked = true;
IE9 及以上版本良好
【讨论】:
【参考方案8】:2014 年对 NodeList
的原生 Symbol.iterator
支持从 added 变为 WHATWG's DOM spec。
不幸的是,Chrome 51 是第一个支持它的 Chrome 版本,在撰写此答案时,它的 Beta 版才刚刚发布。此外,任何版本的 Internet Explorer 或 Edge 都不支持。
要在所有浏览器中将Symbol.iterator
对NodeList
的支持添加到您的代码中,只需使用以下polyfill:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
【讨论】:
【参考方案9】:我遇到了这个问题。原来我是由使用参数而不是数组调用 Promise.all() 引起的。例如:
之前:Promise.all(p1, p2)
之后:Promise.all([p1, p2])
希望这对某人有所帮助。
【讨论】:
这和NodeList有什么关系?以上是关于for 循环 querySelectorAll的主要内容,如果未能解决你的问题,请参考以下文章