2017-01-20 13 views
5

DOM4 делает NodeList сек Iterable:Может ли HTMLCollections повторяться для ... из (Symbol.iterator)?

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

Согласно WebIDL, это означает, что

объектов реализации интерфейса, который объявляется итерируемый поддержка будучи итерации, чтобы получить последовательность значений.

Примечания: В языке ECMAScript связывание, интерфейс, который итерацию будут иметь «запись», «Foreach», «ключи», «ценность» и @@iterator свойства на его interface prototype object.

Так что возможно следующее:

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

я заметил то же самое, кажется, работает для HTMLCollections, как на Firefox и Chrome:

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

На самом деле, я получаю

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

Однако HTMLCollection не является определяется как Iterable:

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

Я также проверил WHATWG DOM spec и это не итерацию ни.

Тогда это стандартное поведение или нет? Предполагается, что HTMLCollection должен иметь @@iterator в прототипе?

+0

http://stackoverflow.com/a/31574921/2813224 – zer00ne

ответ

4

Я нашел его, это объясняется в WebIDL:

Если interface имеет одно из следующих действий:

то свойство должно существовать, чье имя является @@iterator символ, с атрибутами {[[Writable]]: true, [[Enumerable]]: false, [[Конфигурируемый]]: true} и значением которого является function object. [...]

Если интерфейс определяет indexed property getter, то Функция объект %ArrayProto_values%.

В этом случае HTMLCollections имеют индексированный геттер свойство:

getter Element ? item (unsigned long index);

и атрибут целочисленного напечатанный под названием «Длина»:

readonly attribute unsigned long length ;

Поэтому, да, он должен работать , Фактически, он также работал бы для NodeLists, даже если бы они не были объявлены как итерируемые, но тогда у них не было бы свойств entries, forEach, keys и values. Как упоминает @lonesomeday, вероятно, что HTMLCollection не определен как итерируемый, потому что добавление этих методов не будет обратно совместимым из-за того, что получатель namedItem принимает произвольные строки.

+0

Я собираюсь * угадать * это из-за метода 'namedItem' на' HTMLCollection' или оператора. Примечание: Элементы - лучшее решение для представления коллекции элементов. HTMLCollection - это исторический артефакт, который мы не можем избавить сети. " – lonesomeday

+2

@lonesomeday Да, похоже, так как 'namedItem' принимает строку, добавляя такие свойства, как' forEach', могут сломать вещи. – Oriol

0

В JavaScript практически все, что имеет структуру 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..of и ...spread, но если вы беспокойство кастрированного барана это соответствует спецификации, чем я должен сказать вам, что я не имею бакалавр информатики степень еще: P

+0

Спасибо, я уже знал о '@@ iterator', моя забота заключается в том, должен ли' HTMLCollection' возвращать правильный итератор – Oriol

+0

@Oriol Я думаю, что это зависит об осуществлении. Интерфейс HTMLCollection не имеет декларации для итератора, но при его реализации вы можете включить и другой интерфейс. В этом случае HTMLCollection и NodeList представляют собой представления коллекций, которые, несомненно, являются итерабельными. – Burimi