Что такое Iterator и Symbol.iterator в JavaScript?

MiddleJavaScript · Frontend·Обновлено 5 августа 2026
Коротко
Iterator — это объект с методом next(), возвращающим {value, done}. Symbol.iterator — стандартный символ, позволяющий объекту стать итерируемым (использоваться в for...of, spread, деструктуризации).

Iterator и Symbol.iterator в JavaScript

Протокол итератора

Итератор (Iterator) — это объект, реализующий протокол итератора: у него должен быть метод next(), который при каждом вызове возвращает объект вида:

{ value: any, done: boolean }
  • value — текущее значение.
  • done: false — итерация продолжается; done: true — итерация завершена.

Протокол итерируемого объекта

Чтобы объект стал итерируемым (iterable), он должен содержать метод с ключом Symbol.iterator. Этот метод вызывается без аргументов и должен возвращать итератор.

Встроенные итерируемые типы: Array, String, Set, Map, NodeList, аргументы функции (arguments).

Symbol.iterator

Symbol.iterator — это глобальный символ (Symbol), зарезервированный спецификацией. Движок JS автоматически ищет его при использовании:

  • for...of
  • spread-оператора [...iterable]
  • деструктуризации const [a, b] = iterable
  • Array.from(iterable)
  • Promise.all(iterable) и других API

Создание собственного итерируемого объекта

const range = {
  from: 1,
  to: 5,
  [Symbol.iterator]() {
    let current = this.from;
    const last = this.to;
    return {
      next() {
        if (current <= last) {
          return { value: current++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

for (const num of range) {
  console.log(num); // 1, 2, 3, 4, 5
}

console.log([...range]); // [1, 2, 3, 4, 5]

Генераторы как удобный способ создания итераторов

Функции-генераторы автоматически реализуют оба протокола:

function* range(from, to) {
  for (let i = from; i <= to; i++) {
    yield i;
  }
}

// Генератор возвращает объект, у которого есть и next(), и Symbol.iterator
const gen = range(1, 3);
console.log(gen.next()); // { value: 1, done: false }
console.log([...range(1, 3)]); // [1, 2, 3]

Отличие итерируемого от итератора

Итерируемый (Iterable) Итератор (Iterator)
Ключевой метод [Symbol.iterator]() next()
Что возвращает Итератор {value, done}
Примеры Array, Set, Map array[Symbol.iterator]()

Массив — итерируемый, но не итератор. array[Symbol.iterator]() — итератор.

Бесконечные итераторы

function* infiniteCounter() {
  let i = 0;
  while (true) {
    yield i++;
  }
}

const counter = infiniteCounter();
console.log(counter.next().value); // 0
console.log(counter.next().value); // 1
// Никогда не завершится — нужно контролировать вручную

Что хочет услышать интервьюер

Чёткое разграничение понятий: итерируемый объект (iterable) и итератор (iterator) — это разные вещи

Знание, что Symbol.iterator должен возвращать объект с методом next(), а next() должен возвращать {value, done}

Понимание, какие встроенные типы итерируемы (Array, String, Map, Set) и как это использовать

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

Понимание, где движок неявно вызывает Symbol.iterator: for...of, spread, деструктуризация, Array.from

Пример: Ручная реализация итерируемого объекта

// Итерируемый диапазон чисел
const range = {
  from: 1,
  to: 5,
  [Symbol.iterator](): Iterator<number> {
    let current = this.from;
    const last = this.to;
    return {
      next(): IteratorResult<number> {
        if (current <= last) {
          return { value: current++, done: false };
        }
        return { value: undefined as unknown as number, done: true };
      }
    };
  }
};

for (const num of range) {
  console.log(num); // 1 2 3 4 5
}

console.log([...range]); // [1, 2, 3, 4, 5]

Пример: Генератор как итератор

// Генераторная функция автоматически реализует оба протокола
function* fibonacci(): Generator<number> {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const fib = fibonacci();

// Итератор: вызов next() вручную
console.log(fib.next()); // { value: 0, done: false }
console.log(fib.next()); // { value: 1, done: false }
console.log(fib.next()); // { value: 1, done: false }

// Берём первые 7 чисел Фибоначчи через spread с ограничением
function take<T>(iterable: Iterable<T>, n: number): T[] {
  const result: T[] = [];
  for (const item of iterable) {
    result.push(item);
    if (result.length >= n) break;
  }
  return result;
}

console.log(take(fibonacci(), 7)); // [0, 1, 1, 2, 3, 5, 8]

Пример: Проверка итерируемости и ручной вызов итератора

// Проверка, является ли объект итерируемым
function isIterable(obj: unknown): obj is Iterable<unknown> {
  return obj != null && typeof (obj as Record<symbol, unknown>)[Symbol.iterator] === 'function';
}

console.log(isIterable([1, 2, 3]));   // true
console.log(isIterable('hello'));      // true
console.log(isIterable(new Set()));   // true
console.log(isIterable({ a: 1 }));    // false
console.log(isIterable(42));          // false

// Ручной вызов итератора (так делает for...of «под капотом»)
const arr = ['a', 'b', 'c'];
const iterator = arr[Symbol.iterator]();

console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: 'b', done: false }
console.log(iterator.next()); // { value: 'c', done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Типичные ошибки

Путают итерируемый объект (имеет Symbol.iterator) и итератор (имеет next()) — это разные протоколы

Забывают, что Symbol.iterator — это символ, не строка; попытка сделать obj['Symbol.iterator'] не работает

Не возвращают правильную форму из next(): пропускают поле done или value, что ломает for...of

Думают, что обычный объект {} итерируемый — это не так, в отличие от массивов и строк

Смешивают итераторы и генераторы: генератор — удобный способ создать итератор, но не синоним

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее