> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/e-controls/e1-iteration/01-iterable-objects.md).

# 01. Iterable

В JavaScript добавлена новая концепция *“итерируемых”* (iterable) объектов:

* **Итерируемый объект** (Iterable) - это объект или структура данных, чьи элементы должны быть доступны для последовательного перебора. Сама структура данных не обязательно должна быть линейной, но во время итерации элементы из неё извлекаются в последовательном порядке. Итерируемый объект содержит метод, доступный по символу `Symbol.iterator`. Этот метод является фабрикой для объектов-итераторов.
* **Итератор** (Iterator) - объект, реализующий специальный протокол, для обхода элементов в структуре данных. Итераторы используются в тех местах, где нужно передать последовательность данных дальше по назначению -`for-of`, `spread`.

Следующие объекты являются итерируемыми:

* `arguments`
* `Array`
* `String`
* `Set`
* `Map`
* DOM структуры
* Пользовательские объекты, имеющие символ-итератор.

В следующих операциях используется итератор:

* Деструкция на основе паттерна массива
* `for-of` цикл
* `Array.from`
* Spread (`...`)
* Constructors of Maps and Sets
* `Promise.all()`, `Promise.race()`
* `yield*`

На основе итераторов работает множество языковых конструкций, добавленных в ES6:

```javascript
// Array destruction
const [a,b] = new Set(['a', 'b', 'c']);

// for-of loop
for (const x of ['a', 'b', 'c']) {
      console.log(x);
}

// Array.from
const arr = Array.from(new Set(['a', 'b', 'c']));

// spread
const arr = [...new Set(['a', 'b', 'c'])];

// Конструкторы `Set` и `Map`
const map = new Map([[false, 'no'], [true, 'yes']]);
const set = new Set(['a', 'b', 'c']);

// Constructors of Sets and Maps receive iterables:
new Set("123").has("2")                                 // true
new WeakSet(function*() {
    yield {};
    yield myObj;
    yield {};
}()).has(myObj); // true

// Promice.all and Promice.race
Promise.all(iterableOverPromises).then(···);
Promise.race(iterableOverPromises).then(···);

// yield*
yield* anIterable;
```

Особенности итератора:

* Является ли объект итерируемым зависит от наличия на нем метода с ключом `Symbol.iterator`, который возвращает валидный итератор.
* Обычные объекты не являются итерируемыми.
* В отличие от массивов, “перебираемые” объекты могут не иметь “длины” `length`.
* Возможны и бесконечные итераторы. Нет никаких ограничений на `next`, он может возвращать всё новые и новые значения, и это нормально.
* Оператор `spread` автоматически превращает итерируемый объект в массив: `Math.max(...range);`
* Если сам объект реализует протокол итератора, тогда и вызов функции-итератора должен просто возвращать `this`.
* Является ли итератор закрываемым?
* Генераторы являются закрываемыми по умолчанию.
* Не все итераторы сами являются итерируемыми. То есть не на всех итераторах определен `Symbol.iterator` возвращающий `this`.
