【问题标题】:Are HTMLCollection and NodeList iterables?HTMLCollection 和 NodeList 是可迭代的吗?
【发布时间】:2015-09-25 19:32:24
【问题描述】:

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

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

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

for...of 循环将在支持 for...of 的浏览器(如 Firefox 13 及更高版本)中正确循环遍历 NodeList 对象

这似乎证实了 Firefox 的行为。

我在 Chrome 和 Firefox 中都测试了以下代码,并惊讶地发现 Firefox 似乎认为它们是可迭代的,但 Chrome 却没有。另外,火狐认为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>

一个非常奇怪,令人困惑的事情:运行代码 sn-p 与复制它并在 Firefox 中的实际文件/控制台中运行(特别是最后一个比较)产生不同的结果。对这里这种奇怪行为的任何启示也将不胜感激。

【问题讨论】:

标签: javascript ecmascript-6 nodelist htmlcollection


【解决方案1】:

Symbol.iterator 支持 NodeListHTMLCollectionDOMTokenListDOMSettableTokenListdiscussedadded 去年的 WHATWG's DOM spec

【讨论】:

  • 从技术上讲,ES6 和 WHATWG 是不同的委员会。 ES6 委员会认为 WHATWG 仅仅是 ES5 的起点,标准从那里演变而来,从那时起忽略 WHATWG。仍然有人同时是两个委员会的成员,所以我希望在某个时候会向 ES6 委员会建议(尽管更有可能向 ES7 建议,因为 ES7 处于草案模式而 ES6 被认为是“最终的” )
  • 好吧,从技术上讲,ES6 和 WHATWG 都不是委员会。 TC39 是一个标准化 ECMAScript 的委员会。 WHATWG 是一个将相关课程标准化的社区。 TC39 没有将这些类标准化的野心。
【解决方案2】:

不幸的是,还没有。但在它们完成之前,您可以像这样轻松地填充它们:

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

【讨论】:

  • 是的,这正是我现在为HTMLCollection NodeList 所做的事情。奇怪的是,Chrome/Opera 不认为它们是可迭代的,而 Firefox 则认为它们是可迭代的。从目前的 cmets 来看,我猜他们应该是,但我不能 100% 确定。
【解决方案3】:

正如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];

【讨论】:

    【解决方案4】:

    对于尝试使用 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')]
    

    【讨论】:

      猜你喜欢
      • 2019-11-26
      • 2014-06-08
      • 1970-01-01
      • 2023-03-13
      • 2018-10-02
      • 2018-02-16
      • 1970-01-01
      相关资源
      最近更新 更多