Hack Frontend Community

Что такое Symbol.iterator и зачем он нужен

Symbol.iterator — это специальный символ, используемый в JavaScript для создания итерируемых объектов, то есть таких, которые можно перебирать с помощью for...of, оператора расширения (...), или использовать в других случаях, где требуется итерируемый интерфейс.

Итерируемые объекты

Объекты, у которых определён метод с ключом Symbol.iterator, считаются итерируемыми. Это:

  • массивы []
  • строки "hello"
  • множества Set
  • карты Map
  • arguments
  • и другие встроенные коллекции

Пример:

const arr = [1, 2, 3];
for (const value of arr) {
  console.log(value); // 1, 2, 3
}

Здесь arr[Symbol.iterator] автоматически вызывается в for...of.

Как работает Symbol.iterator

Метод Symbol.iterator должен возвращать объект итератора, у которого есть метод next(). Этот метод возвращает объект с двумя свойствами:

  • value — текущее значение
  • done — булево, указывает завершен ли перебор

Пример собственного итератора

const customIterable = {
  data: [10, 20, 30],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.data.length) {
          return { value: this.data[index++], done: false };
        } else {
          return { done: true };
        }
      }
    };
  }
};

for (const num of customIterable) {
  console.log(num); // 10, 20, 30
}

Почему нельзя итерировать обычный объект?

const obj = { a: 1, b: 2 };
for (const key of obj) {
  // TypeError: obj is not iterable
}

Объекты по умолчанию не являются итерируемыми, потому что у них нет метода [Symbol.iterator]. Чтобы сделать объект итерируемым, нужно явно определить этот метод.

Где используется Symbol.iterator

  • for...of
  • spread (...)
  • Array.from()
  • Promise.all
  • Set
  • Map
  • деструктуризация: [...something]

Вывод

  • Symbol.iterator — ключ к итерируемости.
  • Любой объект, реализующий [Symbol.iterator], можно использовать в for...of.
  • Вы можете создавать свои структуры данных, поддерживающие итерацию по вашему сценарию.

Факт:

Именно Symbol.iterator делает возможной работу таких конструкций как for...of, ...spread, и даже yield* в генераторах.