8

DOM4 使NodeList可迭代:

interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};

根据WebIDL,这意味着

实现被声明为可迭代的接口的对象支持被迭代以获得一系列值。

注意:在 ECMAScript 语言绑定中,可迭代的接口将 在其接口原型对象上具有“entries”、“forEach”、“keys”、“values”和@@iterator属性。

所以以下是可能的:

for (var el of document.querySelectorAll(selector)) ...

我注意到在 Firefox 和 Chrome 上似乎同样适用于 HTMLCollections:

for (var el of document.getElementsByTagName(tag)) ...

事实上,我得到

HTMLCollection.prototype[Symbol.iterator] === [][Symbol.iterator]; // true

但是,HTMLCollection没有定义为可迭代的:

interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

我还检查了WHATWG DOM 规范,它也不是可迭代的。

那么,这种行为标准与否?HTMLCollection应该@@iterator在原型中有一个?

4

2 回答 2

7

我找到了,它在WebIDL中有解释:

如果接口出现以下情况:

那么必须存在一个名称为@@iterator符号的属性,其属性为 { [[Writable]]: true , [[Enumerable]]: false , [[Configurable]]: true } 并且其值为函数对象。[...]

如果接口定义了索引属性 getter,则 Function对象为%ArrayProto_values%

在这种情况下,HTMLCollections 有一个索引属性 getter:

getter Element? item(unsigned long index);

和一个名为“length”的整数类型属性:

readonly attribute unsigned long length;

因此,是的,它应该可以工作。事实上,它也适用于 NodeLists,即使它们没有被声明为可迭代的,但是它们不会具有、entriesforEach属性。正如@lonesomeday 所提到的,HTMLCollection 很可能没有被定义为可迭代的,因为添加这些方法不会向后兼容,因为getter 接受任意字符串。keysvaluesnamedItem

于 2017-01-20T08:52:52.483 回答
0

在 JavaScript 中,几乎所有具有 an 结构的东西都iterable可以通过一些迭代引擎操作,例如:for..of...spread

任何东西都是可迭代的,如果它返回一个迭代器来[[Get]]针对它存储的@@iterator符号的属性进行操作,在这种情况下显然HTMLCollection返回这样一个对象。

next() {method}:如果迭代器具有 :和另外两个可选方法,则它本身就被计算在内

return() {method}: stops iterator and returns IteratorResult
throw() {method}: signals error and returns IteratorResult

这是可迭代的完整自定义对象的示例。

    const calculations = {
      counting: 1,
      [Symbol.iterator]: function(){ return this; },
      next: function(){

        if(this.counting <= 3){

          return {
            value: this.counting++,
            done: false
          }
        }

        return { value: this.counting, done: true}
      }
    };

const data = ...calculations; // [1,2,3]

因此,在您的情况下,只要HTMLCollection返回适当的迭代器,您就可以应用for..ofand ...spread,但是如果您担心这是否符合规范,那么我必须告诉您我还没有计算机科学学士学位:P

于 2017-01-20T08:37:32.223 回答