Реализация итератора в JS - PullRequest
0 голосов
/ 25 апреля 2018

Мы можем сделать обычный (POJSO) JS-объект повторяемым, например, так:

const tempObj = {a: 1, b: 2, c: 3};

tempObj[Symbol.iterator] = function () {
  const self = this;
  const keys = Object.keys(self);
  return {
    next() {
      const k = keys.shift();
      return {
        done: !k,
        value: [k, self[k]]
      }
    }
  }
};

Теперь мы можем использовать цикл for..of:

for (let [k,v] of tempObj) {
  console.log(k,v);
}

и получаем:

a 1
b 2
c 3

мой вопрос - есть ли другой метод, который нам нужно реализовать, кроме next ()?если нет, почему спецификация итератора решила вернуть объект, а не просто вернуть функцию?почему спецификация не проста:

   tempObj[Symbol.iterator] = function () {
      return function next {
          return {
            done: Object.keys(this).length === 0,
            value: Object.keys(this).shift()
          }
      }
    };

Я могу только предположить, что, возвращая объект, он оставляет место для обновлений / изменений.

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Интерфейс Iterator также поддерживает еще два дополнительных метода: return и throw.Из спецификации ES6 , раздел 25.1.1.2 (Таблица 54):

return

Функция, которая возвращает объект IteratorResult.Возвращаемый объект должен соответствовать интерфейсу IteratorResult.Вызов этого метода уведомляет объект Iterator о том, что вызывающая сторона не намеревается делать больше следующих вызовов метода для Iterator.Возвращаемый объект IteratorResult обычно будет иметь свойство done, значение которого равно true, и свойство value, значение которого передается в качестве аргумента метода возврата.Однако это требование не выполняется.

throw

Функция, которая возвращает объект IteratorResult.Возвращаемый объект должен соответствовать интерфейсу IteratorResult.Вызов этого метода уведомляет объект Iterator о том, что вызывающая сторона обнаружила условие ошибки.Аргумент может использоваться для идентификации состояния ошибки и, как правило, будет объектом исключения.Типичный ответ - бросить значение, переданное в качестве аргумента.Если метод не выбрасывает, возвращенный объект IteratorResult обычно будет иметь свойство done со значением true.

В спецификации ES6 также указано:

Обычно вызывающиеметоды должны проверять их существование, прежде чем вызывать их.

Таким образом, вы определенно не обязаны их реализовывать;бремя проверки их существования лежит на звонящем.

0 голосов
/ 25 апреля 2018

Есть ли еще один метод, который нам нужно реализовать, кроме next()?

Нет, нет такого, который нам нужен для реализации, но мы можем реализовать throw и return для полного интерфейса итератора .Например, объекты-генераторы делают это.

Почему спецификация итератора решила возвращать объект, а не просто возвращать функцию?

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

0 голосов
/ 25 апреля 2018

Вы можете получить генератор с Object.entries в качестве значения.

let tempObj = { a: 1, b: 2, c: 3 };

tempObj[Symbol.iterator] = function* () {
    yield* Object.entries(this);
};

for (let [k, v] of tempObj) {
    console.log(k, v);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...