HTMLCollection 和 NodeList 是可迭代的吗?

Are HTMLCollection and NodeList iterables?

在 ES6 中,iterable 是一个允许 for... of 的对象,并且有一个 Symbol.iterator 键。

数组是可迭代的,集合和映射也是如此。问题是:HTMLCollection and NodeList 是可迭代的吗?他们应该是吗?

MDN 文档似乎表明 NodeList 是可迭代的。

for...of loops will loop over NodeList objects correctly, in browsers that support for...of (like Firefox 13 and later)

这似乎证实了 Firefox 的行为。

我在 Chrome 和 Firefox 中测试了以下代码,惊讶地发现 Firefox 似乎认为它们是可迭代的,但 Chrome 不是。另外,Firefox 认为 HTMLCollectionNodeList 返回的迭代器是同一个

var col = document.getElementsByClassName('test'); // Should get HTMLCollection of 2 elems
var nod = document.querySelectorAll('.test');      // Should get NodeList of 2 elems
var arr = [].slice.call(col);                      // Should get Array of 2 elems

console.log(col[Symbol.iterator]);    // Firefox: iterator function, Chrome: undefined
console.log(nod[Symbol.iterator]);    // Firefox: iterator function, Chrome: undefined
console.log(arr[Symbol.iterator]);    // Firefox & Chrome: iterator function
console.log(col[Symbol.iterator] === nod[Symbol.iterator]);  // Firefox: true
console.log(col[Symbol.iterator] === arr[Symbol.iterator]);  // Firefox: false
<div class="test">1</div>
<div class="test">2</div>

一个非常奇怪、令人困惑的事情:运行 代码片段产生的结果与复制它和 运行 在实际 file/console 在 Firefox 中(特别是最后的比较)。对这里这种奇怪行为的任何启发也将不胜感激。

Symbol.iteratorNodeListHTMLCollectionDOMTokenListDOMSettableTokenList 的支持在去年是 discussed and added to the WHATWG's DOM spec

很遗憾,还没有。但在它们出现之前,您可以像这样轻松地填充它们:

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

正如 greiner 指出的那样,在 2014 年 WHATWG 的 DOM 规范中添加了对 NodeList 的原生 Symbol.iterator 支持。

不幸的是,Chrome 51 是第一个支持它的 Chrome 版本,在撰写此答案时其 Beta 才刚刚发布。此外,任何版本的 Internet Explorer 或 Edge 均不支持。

要在所有浏览器中为您的代码添加 Symbol.iteratorNodeList 的支持,只需使用以下 polyfill:

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

对于尝试使用 TypeScript 迭代 NodeList 到达这里的任何人。我在修复 https://github.com/microsoft/TypeScript/issues/4947 时发现了这个问题,这是您需要的 tsconfig.json

{
  "compilerOptions": {
    "lib": ["es2017", "dom", "dom.iterable"],
    "downlevelIteration": true
  }
}

我遇到的问题错误:

Type 'NodeListOf<Element>' is not an array type.

这是触发该问题的代码:

[...document.querySelectorAll('#md-view a')]