Паттерн Итератор (Iterator Pattern) предоставляет способ последовательного доступа к элементам коллекции без раскрытия её внутреннего представления. Итератор инкапсулирует логику обхода коллекции, что позволяет использовать единообразный способ перебора различных типов коллекций. Это упрощает работу с коллекциями и делает код более читаемым и поддерживаемым.
В примере ниже реализованы два итератора: ArrayIterator для массивов и ObjectIterator для объектов. Оба итератора
предоставляют одинаковый интерфейс (next() и hasNext()), что позволяет использовать единообразный способ перебора
различных типов коллекций. Итератор скрывает внутреннюю структуру данных и не позволяет напрямую изменять коллекцию
во время обхода.
// Итератор для массивов
class ArrayIterator {
constructor(collection) {
this.collection = collection;
this.currentIndex = 0;
}
next() {
return this.collection[this.currentIndex++];
}
hasNext() {
return this.currentIndex < this.collection.length;
}
reset() {
this.currentIndex = 0;
}
}
// Итератор для объектов
class ObjectIterator {
constructor(collection) {
this.collection = collection;
this.keys = Object.keys(collection);
this.currentIndex = 0;
}
next() {
const key = this.keys[this.currentIndex++];
return {
key,
value: this.collection[key]
};
}
hasNext() {
return this.currentIndex < this.keys.length;
}
reset() {
this.currentIndex = 0;
}
}
// Пример 1: Итерация по массиву
console.log('=== Array Iterator ===');
const arrayIterator = new ArrayIterator(['1', '2', '3', '4', '5']);
while (arrayIterator.hasNext()) {
console.log(arrayIterator.next());
}
// Output: '1', '2', '3', '4', '5'
// Пример 2: Итерация по объекту
console.log('\n=== Object Iterator ===');
const objectIterator = new ObjectIterator({
name: 'Kirill',
job: 'Frontend',
hobby: 'Coding'
});
while (objectIterator.hasNext()) {
const item = objectIterator.next();
console.log(`${item.key}: ${item.value}`);
}
// Output:
// name: Kirill
// job: Frontend
// hobby: Coding
// Пример 3: Универсальная функция для перебора любых коллекций
function iterateCollection(iterator) {
const results = [];
while (iterator.hasNext()) {
results.push(iterator.next());
}
return results;
}
console.log('\n=== Universal Iteration ===');
const numbers = new ArrayIterator([10, 20, 30]);
console.log(iterateCollection(numbers)); // [10, 20, 30]
const user = new ObjectIterator({
id: 1,
email: 'user@example.com',
role: 'admin'
});
console.log(iterateCollection(user));
// [{ key: 'id', value: 1 }, { key: 'email', value: 'user@example.com' }, ...]
// Пример 4: Использование reset для повторного обхода
console.log('\n=== Reset Iterator ===');
const colors = new ArrayIterator(['red', 'green', 'blue']);
console.log('First iteration:');
while (colors.hasNext()) {
console.log(colors.next());
}
colors.reset();
console.log('Second iteration (after reset):');
while (colors.hasNext()) {
console.log(colors.next());
}