Проверяет понимание протоколов итерации в JavaScript и возможности создания объекта, реализующего оба интерфейса.
В JavaScript существуют два тесно связанных протокола: iterable (итерируемый) и iterator (итератор). Iterable — это объект, который определяет способ итерации, реализуя метод Symbol.iterator. Iterator — это объект с методом next(), который возвращает следующий элемент последовательности. Обычно это разные объекты, но технически один объект может совмещать обе роли.
Чтобы объект был iterable, он должен иметь метод Symbol.iterator, который возвращает iterator. Если этот метод возвращает сам объект (this), то объект становится одновременно и iterable, и iterator. При этом он должен также реализовать метод next() с правильной логикой.
const customIterable = {
current: 0,
max: 5,
[Symbol.iterator]() {
return this; // возвращаем себя как итератор
},
next() {
if (this.current < this.max) {
return { value: this.current++, done: false };
}
return { value: undefined, done: true };
}
};
for (const num of customIterable) {
console.log(num); // 0, 1, 2, 3, 4
}Такой подход полезен для создания простых кастомных итераторов, когда не требуется разделение ответственности между итерируемым объектом и итератором. Однако стоит помнить, что такой объект может быть использован только в одной итерации одновременно, так как состояние итерации хранится в самом объекте.
Совмещение iterable и iterator в одном объекте — это допустимый, но нишевый приём. Его стоит применять для простых сценариев, где не нужна поддержка множественных одновременных итераций, и когда важна компактность кода.