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 迭代 NodeLists,看来这是一个浏览器错误,或者至少是浏览器缺乏。

我目前使用的用户脚本的实际工作代码:

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 迭代,而不是使用fromcall【参考方案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.iteratorNodeList 的支持添加到您的代码中,只需使用以下polyfill:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

【讨论】:

【参考方案9】:

我遇到了这个问题。原来我是由使用参数而不是数组调用 Promise.all() 引起的。例如:

之前:Promise.all(p1, p2)

之后:Promise.all([p1, p2])

希望这对某人有所帮助。

【讨论】:

这和NodeList有什么关系?

以上是关于for 循环 querySelectorAll的主要内容,如果未能解决你的问题,请参考以下文章

两个for循环执行顺序

java 后执行的for循环比先执行的for循环速度快

for循环执行顺序?

如何确定for循环的次数!

如何确定for循环的次数

C语言中for循环怎么理解?