Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что можно итерировать: Iterables и Iterator протокол
Итерировать - значит проходить по элементам последовательности один за другим. В JavaScript это можно делать только с объектами, которые реализуют Iterator протокол. Не все объекты можно итерировать - это важное различие, которое часто забывают.
Встроенные итерируемые объекты
1. Массив
const arr = [1, 2, 3];
// for...of
for (const item of arr) {
console.log(item); // 1, 2, 3
}
// Array.prototype.forEach
arr.forEach(item => console.log(item));
// Spread оператор
const copy = [...arr];
2. Строка
const str = 'hello';
// for...of - итерирует по символам
for (const char of str) {
console.log(char); // h, e, l, l, o
}
// Spread оператор
const chars = [...str]; // ['h', 'e', 'l', 'l', 'o']
3. Set
const set = new Set([1, 2, 3, 1]); // {1, 2, 3}
for (const value of set) {
console.log(value); // 1, 2, 3
}
// Set в массив
const arr = [...set];
4. Map
const map = new Map([
['name', 'Alice'],
['age', 25]
]);
for (const [key, value] of map) {
console.log(key, value); // name Alice, age 25
}
// Итерация только по ключам
for (const key of map.keys()) {
console.log(key); // name, age
}
// Итерация только по значениям
for (const value of map.values()) {
console.log(value); // Alice, 25
}
5. Arguments объект (в классических функциях)
function printArgs() {
for (const arg of arguments) {
console.log(arg);
}
}
printArgs('a', 'b', 'c'); // a, b, c
6. NodeList (DOM API)
const elements = document.querySelectorAll('button');
for (const element of elements) {
element.addEventListener('click', () => {
console.log('Clicked');
});
}
Что НЕЛЬЗЯ итерировать
Обычный объект
const obj = { name: 'Alice', age: 25 };
// ОШИБКА!
for (const item of obj) {
console.log(item);
}
// TypeError: obj is not iterable
// Нужно использовать Object.keys, Object.values, Object.entries
for (const key of Object.keys(obj)) {
console.log(key); // name, age
}
for (const value of Object.values(obj)) {
console.log(value); // Alice, 25
}
for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // name Alice, age 25
}
Число
const num = 123;
// ОШИБКА!
for (const digit of num) {
console.log(digit);
}
// TypeError: num is not iterable
// Правильно - конвертируем в строку
for (const digit of String(num)) {
console.log(digit); // 1, 2, 3
}
null и undefined
const value = null;
// ОШИБКА!
for (const item of value) {
console.log(item);
}
// TypeError: Cannot read properties of null
Iterator Протокол
Итерируемый объект должен иметь метод Symbol.iterator, который возвращает Iterator.
Iterator должен иметь метод next(), который возвращает объект {value, done}.
// Как работает Iterator протокол
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Создание своего итерируемого объекта
class Counter {
constructor(max) {
this.max = max;
}
// Делаем объект итерируемым
[Symbol.iterator]() {
let current = 1;
const max = this.max;
return {
next() {
if (current <= max) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
}
const counter = new Counter(3);
for (const num of counter) {
console.log(num); // 1, 2, 3
}
// Spread оператор тоже работает
const arr = [...counter]; // [1, 2, 3]
Generator функции - простой способ создать Iterator
function* generateNumbers() {
yield 1;
yield 2;
yield 3;
}
const gen = generateNumbers();
for (const num of gen) {
console.log(num); // 1, 2, 3
}
// Generator функция вернёт то же самое
const arr = [...generateNumbers()]; // [1, 2, 3]
Практический пример: Пользовательская коллекция
class SimpleList {
constructor() {
this.items = [];
}
add(item) {
this.items.push(item);
return this; // Chainable API
}
[Symbol.iterator]() {
let index = 0;
const items = this.items;
return {
next() {
if (index < items.length) {
return { value: items[index++], done: false };
} else {
return { done: true };
}
}
};
}
}
const list = new SimpleList()
.add('apple')
.add('banana')
.add('cherry');
for (const item of list) {
console.log(item); // apple, banana, cherry
}
for...of vs for...in
const arr = ['a', 'b', 'c'];
arr.custom = 'extra';
// for...in - перебирает свойства (включая пользовательские)
for (const index in arr) {
console.log(index); // 0, 1, 2, 'custom'
}
// for...of - перебирает значения (только итерируемые элементы)
for (const value of arr) {
console.log(value); // a, b, c
}
Реальный пример: API обработка
class APIResponse {
constructor(data) {
this.data = data;
this.index = 0;
}
// Делаем ответ итерируемым
*[Symbol.iterator]() {
while (this.index < this.data.length) {
yield this.data[this.index++];
}
}
}
const response = new APIResponse([
{ id: 1, name: 'User 1' },
{ id: 2, name: 'User 2' },
{ id: 3, name: 'User 3' }
]);
// Легко обрабатывать результаты
for (const user of response) {
console.log(user.name);
}
// Можно фильтровать
const users = [...response].filter(u => u.id > 1);
Проверка, является ли объект итерируемым
function isIterable(obj) {
return obj != null && typeof obj[Symbol.iterator] === 'function';
}
console.log(isIterable([1, 2, 3])); // true
console.log(isIterable('hello')); // true
console.log(isIterable(new Set([1, 2]))); // true
console.log(isIterable({ a: 1 })); // false
console.log(isIterable(123)); // false
Распространённые ошибки
// Ошибка 1: Попытка итерировать объект
const obj = { a: 1, b: 2 };
const items = [...obj]; // TypeError!
// Исправление
const items = Object.values(obj); // [1, 2]
// Ошибка 2: Забыть про done: true
function* badGenerator() {
yield 1;
yield 2;
// Забыли return
}
const gen = badGenerator();
console.log([...gen]); // [1, 2] - работает, но не явно
// Правильно
function* goodGenerator() {
yield 1;
yield 2;
return 3; // Явно возвращаем значение
}
Итог
Можно итерировать:
- Массивы
- Строки
- Set и Map
- NodeList и HTMLCollection
- Arguments
- Пользовательские объекты с Symbol.iterator
Нельзя итерировать:
- Обычные объекты (используй Object.keys/values/entries)
- Числа
- null и undefined
Для работы с неитерируемыми объектами: используй Object.keys(), Object.values(), Object.entries() или преобразуй в итерируемый формат.