С итерируемыми объектами работают только циклы
for-
of и
for-
await-
of.
В современном JS есть следующие виды циклов:
1.
while - цикл с условием
// где condition - это некоторое выражение, которое можно скастовать к boolean
while (condition) {
}
Данный цикл выполняется, пока условие condition истинно.
2.
do-
while - цикл с постусловием
do {
} while (condition);
Данный цикл выполняется как минимум 1 раз, условие condition проверяется после тела цикла и если оно истинно - запускается следующая итерация.
3.
for - цикл с инициализацией, условием и финальным выражением
for (init; condition; final_expression) {
}
// основное применение - это цикл со счетчиком, но в целом мы не ограничены в применении
for (let i = 0; i < 10; ++i) {
}
Перед циклом выполняется init, который может быть выражением или оператором объявления переменных (
var,
let,
const). Перед каждой итерацией проверяется условие condition, пока это условие истинно - цикл будет выполняться. После каждой итерации выполняется final_expression.
4.
for-
in - цикл по ключам объекта
// где object - это некоторое выражение, которое можно скастовать к типу object
for (const key in object) {
}
Данный цикл перебирает все перечислимые ключи самого объекта и
всех объектов из его цепочки прототипов. Может работать медленно, а ключи из прототипа обычно не требуются, поэтому данный цикл не рекомендуется использовать.
5.
for-
of - цикл по итерируемым объектам
// где iterable - это некоторый объект с методом Symbol.iterator
for (const value_variable of iterable) {
}
Перед итерацией создает итератор вызывая
iterable[Symbol.iterator]()
, перед каждой итерацией дергает метод next у итератора, работает пока в возвращаемом из метода next объекте поле done не станет true, подставляет поле value в переменную value_variable. Цикл в примере выше можно реализовать в виде обычного
for:
{
const iter = [1, 2, 3][Symbol.iterator]();
for (let {done, value} = iter.next(); !done; ({done, value} = iter.next())) {
const value_variable = value;
{
// тело исходного цикла
}
}
}
6.
for-
await-
of - цикл по асинхронно итерируемым объектам
// где iterable - это некоторый объект с методом Symbol.asyncIterator или методом Symbol.iterator
for await (const value_variable of iterable) {
}
Перед итерацией создает итератор, одним из следующих способов:
Если в объекте iterable есть метод Symbol.asyncIterator - то вызывает его.
В противном случае вызывает метод Symbol.iterator.
В остальном работает как
for-
of, с той разницей, что дополнительно применяет оператор
await к значению итератора и в value_variable попадает то, что вернул данный
await.