← Назад к вопросам

Как сделать объект итерируемым?

2.0 Middle🔥 202 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как сделать объект итерируемым в JavaScript

В JavaScript итерируемым (iterable) называется объект, который реализует протокол Iterable Protocol. Это позволяет объекту участвовать в циклах for...of, использоваться с оператором spread (...), деструктуризацией и в других контекстах, ожидающих перечисляемые значения (например, Array.from()).

Основной механизм: метод [Symbol.iterator]()

Чтобы сделать объект итерируемым, в него необходимо добавить метод с ключом Symbol.iterator. Этот метод должен возвращать объект, соответствующий Iterator Protocol – то есть объект с методом next(), который возвращает объект вида { value: any, done: boolean }.

Пример создания простого итерируемого объекта:

const myIterableObject = {
  data: [10, 20, 30],
  
  // Реализуем протокол итерируемости
  [Symbol.iterator]() {
    let index = 0;
    const data = this.data;
    
    // Возвращаем объект-итератор
    return {
      next() {
        if (index < data.length) {
          return { value: data[index++], done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
};

// Теперь объект можно использовать в for...of
for (const value of myIterableObject) {
  console.log(value); // 10, 20, 30
}

// Также работает с spread оператором
const arrayFromObject = [...myIterableObject]; // [10, 20, 30]

Ключевые аспекты реализации

  1. Символ Symbol.iterator – специальное значение, используемое как ключ для метода, делающего объект итерируемым.

  2. Объект-итератор – должен иметь метод next(), который при каждом вызове возвращает следующий элемент последовательности.

  3. Состояние итератора – каждый вызов [Symbol.iterator]() должен возвращать новый итератор с собственным состоянием, что позволяет иметь несколько независимых итераций над одним объектом.

Расширенный пример с дополнительными возможностями

class Range {
  constructor(start, end, step = 1) {
    this.start = start;
    this.end = end;
    this.step = step;
  }
  
  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;
    const step = this.step;
    
    return {
      next() {
        if ((step > 0 && current <= end) || (step < 0 && current >= end)) {
          const value = current;
          current += step;
          return { value, done: false };
        }
        return { value: undefined, done: true };
      },
      
      // Необязательный метод return() для преждевременного завершения итерации
      return() {
        console.log('Итерация прервана');
        return { done: true };
      }
    };
  }
}

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

Встроенные итерируемые объекты

В JavaScript многие встроенные объекты уже являются итерируемыми:

  • Массивы (Array)
  • Строки (String)
  • Map и Set
  • NodeList в DOM
  • Аргументы функции (arguments)

Практические применения

  1. Ленивые вычисления – генерация значений по мере необходимости
  2. Работа с бесконечными последовательностями
  3. Интеграция с асинхронными операциями через асинхронные итераторы (Symbol.asyncIterator)
  4. Кастомные структуры данных – деревья, графы, очереди
// Пример с генерацией последовательности Фибоначчи
const fibonacci = {
  [Symbol.iterator]() {
    let [prev, current] = [0, 1];
    
    return {
      next() {
        [prev, current] = [current, prev + current];
        return { value: prev, done: false };
      }
    };
  }
};

// Берем первые 10 чисел Фибоначчи
const firstTen = [...fibonacci].slice(0, 10);

Важные нюансы

  • Итераторы могут быть одноразовыми или многоразовыми, в зависимости от реализации
  • Метод next() может принимать аргументы, что используется в генераторах
  • Для асинхронной итерации используется Symbol.asyncIterator
  • Протокол итераторов тесно связан с генераторными функциями, которые значительно упрощают создание итерируемых объектов

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