Цикл for и перебор коллекций
Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.
Цикл — это способ сказать «повтори ещё раз», не переписывая код руками. В JavaScript есть три разных for: один считает, второй достаёт значения, третий — ключи, и путать их больно.
В круглых скобках for живут три части, разделённые точкой с запятой: счётчик (выполняется один раз перед стартом), условие (проверяется перед каждым проходом) и шаг (выполняется после каждого прохода). Пока условие истинно, тело повторяется.
Порядок такой: let i = 0 → проверка i < 3 → тело → i++ → снова проверка. Как только условие даёт false, цикл заканчивается и выполнение идёт дальше. Переменную i видно только внутри цикла — она объявлена через let прямо в заголовке.
Такой for берут, когда нужен именно номер шага: идти через один, считать назад, пройти половину массива. Если номер не нужен — есть варианты приятнее.
for..of проходит по значениям коллекции и отдаёт их по одному. Никаких i, никакой длины, никакой возможности промахнуться мимо границы массива.
Переменную объявляют через const: на каждой итерации она создаётся заново, так что переприсваивать её обычно не нужно. Работает for..of не только с массивами — строка тоже перебирается посимвольно, и Map с Set тоже умеют.
У массива есть метод entries() — он выдаёт пары «индекс, значение». Пару удобно сразу разобрать по переменным в квадратных скобках, это называется деструктуризацией.
for..in перебирает ключи объекта. Значение достают уже вручную — через квадратные скобки, потому что имя свойства лежит в переменной.
Для массивов for..in формально работает, но это ловушка. Во-первых, ключи приходят строками: "0", а не 0. Во-вторых, он выдаёт все перечислимые свойства, а не только элементы — если кто-то добавил массиву обычное свойство, оно тоже попадёт в перебор.
in — ключи, of — значения. Два слова, а сколько сэкономленных часов.
Тело цикла — обычный код, значит внутри может стоять ещё один цикл. Внешний делает один шаг — внутренний успевает пройти целиком. Отсюда простое правило подсчёта: два цикла по три шага дают девять повторений тела.
Чаще всего вложенность нужна для «массива массивов» — таблицы, игрового поля, матрицы. Внешний цикл идёт по строкам, внутренний — по ячейкам строки.
Обычный break прерывает только тот цикл, в котором стоит. Чтобы выпрыгнуть из обоих, циклу дают метку — имя с двоеточием — и пишут break имя. Метки, а вместе с ними break и continue целиком, разбирает статья «break и continue: управление циклом».
Кроме циклов у массива есть метод forEach: он сам зовёт вашу функцию для каждого элемента и передаёт в неё значение и индекс. Выглядит компактно и хорошо читается.
У forEach есть цена: из него нельзя выйти досрочно. break там — синтаксическая ошибка, а return завершает лишь текущий вызов функции. Нужен ранний выход — берите for..of.
| Способ | Что в руках | Можно break |
|---|---|---|
| for (let i = 0; ...) | индекс i | да |
| for..of | значение | да |
| for..in | ключ, всегда строка | да |
| forEach | значение и индекс | нет |
Практический выбор простой: перебираете значения массива — for..of; нужен хитрый шаг или номер — классический for; идёте по свойствам объекта — for..in.
- Классический
for(;;)состоит из счётчика, условия и шага; берите его, когда нужен номер итерации или нестандартный шаг. for..ofотдаёт значения массива, строки,MapилиSet— самый частый выбор для перебора коллекции.for..inперебирает ключи объекта; для массивов он опасен: ключи приходят строками и попадают лишние свойства.- Вложенные циклы проходят «таблицу»: внешний идёт по строкам, внутренний — по ячейкам; выйти сразу из обоих помогает метка и
break имя. forEachчитается компактно, но прерваться в нём нельзя — там, где нуженbreak, используйтеfor..of.
1/3Что выведет этот код?const arr = ["a", "b"];
for (const x in arr) console.log(x);
2/3Сколько раз выполнится тело цикла for (let i = 10; i > 7; i--)?
3/3Из какого перебора нельзя выйти досрочно через break?
Сумма чётных чисел
Дан массив чисел. Посчитайте сумму только чётных элементов и выведите её. Чётность проверяется остатком от деления: n % 2 === 0.
Индексы здесь не нужны — достаточно значений, поэтому берём for..of и прибавляем к сумме только те числа, у которых остаток от деления на 2 равен нулю.
Считаются 8 и 10, вместе они дают 18. Через классический for вышло бы столько же строк, но пришлось бы писать nums[i] и следить за границей массива.
Таблица умножения 3×3
С помощью вложенных циклов выведите три строки таблицы умножения: в каждой — числа от i * 1 до i * 3, склеенные через пробел. Ниже показан ожидаемый вывод.
Внешний цикл отвечает за номер строки, внутренний собирает её содержимое в текстовую переменную. Печатаем строку после того, как внутренний цикл закончил работу.
Метод trim() убирает лишний пробел в конце. Важная деталь: let row объявлена внутри внешнего цикла — если вынести объявление наружу, все строки склеятся в одну длинную.