Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем нужен Symbol.iterator?
Symbol.iterator — это встроенный символ JavaScript, который определяет, как объект должен быть перебран. Это ключевой элемент протокола итерирования, который позволяет использовать объекты в цикле for...of, деструктурировании и других конструкциях, требующих последовательного обхода.
Основная цель
Symbol.iterator позволяет:
- Делать объект итерируемым (iterable)
- Использовать его в конструкциях
for...of - Применять spread оператор (
...) - Деструктурировать значения
- Передавать в функции, ожидающие итерируемых объектов
Как работает протокол итерирования
// Объект с методом Symbol.iterator
const myObject = {
data: [1, 2, 3, 4, 5],
[Symbol.iterator]() {
let index = 0;
const data = this.data;
return {
next: () => {
if (index < data.length) {
return { value: data[index++], done: false };
} else {
return { done: true };
}
}
};
}
};
// Теперь можно использовать for...of
for (const value of myObject) {
console.log(value); // 1, 2, 3, 4, 5
}
Встроенные итерируемые объекты
Множество встроенных типов данных уже имеют Symbol.iterator:
// Array
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item);
}
// String
const str = 'Hello';
for (const char of str) {
console.log(char); // H, e, l, l, o
}
// Map
const map = new Map([['a', 1], ['b', 2]]);
for (const [key, value] of map) {
console.log(key, value); // a 1, b 2
}
// Set
const set = new Set([1, 2, 3]);
for (const value of set) {
console.log(value); // 1, 2, 3
}
Создание собственного итератора
// Класс для генерации диапазона чисел
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next: () => {
if (current <= end) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
}
// Использование
const range = new Range(1, 5);
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
// Можно использовать spread оператор
const arr = [...range];
console.log(arr); // [1, 2, 3, 4, 5]
// Деструктурирование
const [first, second, ...rest] = range;
console.log(first, second, rest); // 1, 2, [3, 4, 5]
Бесконечный итератор
// Итератор, возвращающий бесконечную последовательность
const infiniteCounter = {
[Symbol.iterator]() {
let count = 0;
return {
next: () => {
return { value: count++, done: false }; // Никогда не кончается
}
};
}
};
// Использование с break
for (const num of infiniteCounter) {
if (num >= 5) break;
console.log(num); // 0, 1, 2, 3, 4
}
Генераторы и Symbol.iterator
Генераторы автоматически реализуют протокол итерирования:
// Генератор функция
function* generateNumbers() {
yield 1;
yield 2;
yield 3;
}
const gen = generateNumbers();
// Генератор имеет Symbol.iterator
for (const num of gen) {
console.log(num); // 1, 2, 3
}
// Эквивалент с явным Symbol.iterator
function* fibonacciGenerator() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacciGenerator();
let count = 0;
for (const num of fib) {
if (count++ >= 5) break;
console.log(num); // 1, 1, 2, 3, 5
}
Практический пример: итератор для древовидной структуры
class TreeNode {
constructor(value) {
this.value = value;
this.children = [];
}
[Symbol.iterator]() {
const queue = [this];
return {
next: () => {
if (queue.length === 0) {
return { done: true };
}
const node = queue.shift();
queue.push(...node.children);
return { value: node.value, done: false };
}
};
}
}
const root = new TreeNode('A');
const b = new TreeNode('B');
const c = new TreeNode('C');
const d = new TreeNode('D');
root.children.push(b, c);
b.children.push(d);
// BFS обход через for...of
for (const value of root) {
console.log(value); // A, B, C, D
}
Проверка итерируемости
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())); // true
console.log(isIterable({ a: 1 })); // false (обычный объект)
console.log(isIterable(123)); // false
Итоги
- Symbol.iterator определяет протокол итерирования для объектов
- Позволяет использовать объект в
for...of, spread оператор и деструктурирование - Встроенные типы (Array, String, Map, Set) уже реализуют этот протокол
- Можно создавать собственные итерируемые объекты с помощью метода
[Symbol.iterator]() - Генераторы автоматически реализуют протокол итерирования
- Это фундаментальный механизм для организации последовательного обхода данных в JavaScript