Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работает iterable в JavaScript
Iterable — это один из фундаментальных концептов современного JavaScript, позволяющий создавать и работать с последовательностями данных. Это важно понимать при работе с циклами, особенно в React при рендеринге списков.
Определение Iterable
Объект считается iterable (итерируемым), если он реализует метод Symbol.iterator, который возвращает iterator:
// Проверить, является ли объект iterable
const obj = [1, 2, 3];
console.log(typeof obj[Symbol.iterator]); // 'function'
// Получить iterator
const iterator = obj[Symbol.iterator]();
console.log(typeof iterator.next); // 'function'
// Iterator имеет метод next(), который возвращает объект
const result = iterator.next();
console.log(result); // { value: 1, done: false }
Встроенные Iterable типы
// Массивы
const arr = [1, 2, 3];
for (const item of arr) {
console.log(item);
}
// Строки
const str = 'hello';
for (const char of str) {
console.log(char); // h, e, l, l, o
}
// Set
const set = new Set([1, 2, 3]);
for (const value of set) {
console.log(value);
}
// Map
const map = new Map([['a', 1], ['b', 2]]);
for (const [key, value] of map) {
console.log(key, value);
}
// Object НЕ является iterable по умолчанию!
const obj = { a: 1, b: 2 };
// for (const item of obj) {} // ОШИБКА: obj is not iterable
// Но можно итерировать его ключи
for (const key of Object.keys(obj)) {
console.log(key);
}
Создание собственного Iterable
// Простой iterable
const myIterable = {
[Symbol.iterator]() {
let count = 0;
return {
next: () => {
count++;
if (count <= 3) {
return { value: count, done: false };
}
return { done: true };
}
};
}
};
for (const value of myIterable) {
console.log(value); // 1, 2, 3
}
// Более практичный пример: класс Range
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 };
}
return { done: true };
}
};
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
Generator функции — простой способ создать Iterable
// Generator функция возвращает iterator
function* countUp(max) {
for (let i = 1; i <= max; i++) {
yield i;
}
}
for (const num of countUp(3)) {
console.log(num); // 1, 2, 3
}
// Generator с условиями
function* fibonacci(limit) {
let [prev, curr] = [0, 1];
while (curr < limit) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
for (const fib of fibonacci(100)) {
console.log(fib); // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
}
// Generator с параметрами
function* repeat(value, times) {
for (let i = 0; i < times; i++) {
yield value;
}
}
const repeated = [...repeat('hello', 3)];
console.log(repeated); // ['hello', 'hello', 'hello']
Spread оператор и Iterable
// Spread оператор работает с любыми iterable
const arr = [1, 2, 3];
const newArr = [...arr, 4, 5];
console.log(newArr); // [1, 2, 3, 4, 5]
// Со строками
const chars = [...'hello'];
console.log(chars); // ['h', 'e', 'l', 'l', 'o']
// С Set
const unique = [...new Set([1, 2, 2, 3, 3])];
console.log(unique); // [1, 2, 3]
// С Map
const mapToArray = [...new Map([['a', 1], ['b', 2]])];
console.log(mapToArray); // [['a', 1], ['b', 2]]
Iterable в React
// При рендеринге списков React ожидает iterable
function TodoList({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}
// map работает с массивом (iterable)
const items = [{ id: 1, title: 'Learn' }, { id: 2, title: 'Code' }];
<TodoList items={items} />
// Можно передать и Set, но нужно перевести в массив
const itemsSet = new Set(items);
<TodoList items={[...itemsSet]} /> // Преобразуем в массив
// JSX поддерживает iterable в шаблонах
function App() {
const range = new Range(1, 5);
return (
<div>
{[...range].map(num => <span key={num}>{num}</span>)}
</div>
);
}
Различие между Iterable и Iterator
// ITERATOR — объект с методом next()
const iterator = {
next() {
// возвращает { value, done }
}
};
// ITERABLE — объект с методом Symbol.iterator
const iterable = {
[Symbol.iterator]() {
// возвращает iterator
}
};
// Массив — это ITERABLE
const arr = [1, 2, 3];
console.log(typeof arr[Symbol.iterator]); // 'function'
// Array.prototype[Symbol.iterator]() возвращает ITERATOR
const iter = arr[Symbol.iterator]();
console.log(typeof iter.next); // 'function'
Практический пример: кастомная коллекция
class Queue {
constructor() {
this.items = [];
}
enqueue(item) {
this.items.push(item);
}
dequeue() {
return this.items.shift();
}
[Symbol.iterator]() {
let index = 0;
const items = this.items;
return {
next: () => {
if (index < items.length) {
return { value: items[index++], done: false };
}
return { done: true };
}
};
}
}
const queue = new Queue();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
// Теперь можно итерировать Queue
for (const item of queue) {
console.log(item); // 1, 2, 3
}
// И использовать spread
const arr = [...queue]; // [1, 2, 3]
Асинхронный Iterable (async iterable)
// Асинхронный iterator
const asyncIterable = {
async *[Symbol.asyncIterator]() {
for (let i = 1; i <= 3; i++) {
await new Promise(resolve => setTimeout(resolve, 100));
yield i;
}
}
};
// Используется with for-await-of
async function demo() {
for await (const value of asyncIterable) {
console.log(value); // 1, 2, 3 (с задержкой)
}
}
// Практический пример: потоковая обработка данных
async function* fetchPages(url) {
let page = 1;
while (true) {
const response = await fetch(`${url}?page=${page}`);
const data = await response.json();
if (data.length === 0) break;
for (const item of data) {
yield item;
}
page++;
}
}
// Использование
for await (const item of fetchPages('/api/items')) {
console.log(item);
}
Выводы
- Iterable — объект с методом Symbol.iterator
- Iterator — объект с методом next() возвращающим {value, done}
- Встроенные типы (Array, String, Set, Map) — итерируемы
- Используй generator функции для простого создания iterable
- Spread оператор (...) работает с любыми iterable
- В React передавай массивы в map(), но можешь использовать любой iterable, преобразовав его в массив
- Async iterable используется для асинхронной обработки потоков данных