Глиф Учебники

Урок 5. Циклы: for, while и for...of

Курс «JavaScript» · урок 5 из 10 · 4 минуты чтения

Цикл повторяет блок кода, пока выполняется условие. Без циклов, чтобы вывести числа от 1 до 100, пришлось бы написать сто строк console.log. С циклом — три.

Цикл for

JavaScript
for (let i = 1; i <= 5; i++) {
  console.log("Шаг " + i);
}
Вывод
Шаг 1
Шаг 2
Шаг 3
Шаг 4
Шаг 5

В скобках после for — три части через точку с запятой:

  1. let i = 1 — начало: выполняется один раз, до цикла. Обычно здесь заводят счётчик.
  2. i <= 5 — условие: проверяется перед каждым повтором. Пока оно верно, тело цикла выполняется.
  3. i++ — шаг: выполняется после каждого повтора, здесь счётчик растёт на единицу.
for (let i = 1; i <= 5; i++) { 1 2 3 let i = 1 1 начало i <= 5 2 условие да console.log("Шаг " + i); тело i++ 3 шаг снова нет после цикла значения i 1 2 3 4 5 6 — условие ложно
Начало let i = 1 выполняется один раз, потом перед каждым повтором проверяется условие i <= 5, после тела выполняется шаг i++; при i = 6 условие ложно, и цикл заканчивается.

Один проход тела цикла называют итерацией. Счётчик i объявлен через let и существует только внутри цикла: после цикла имени i нет.

Сумма чисел от 1 до 100 — классическая задача на цикл:

JavaScript
let sum = 0;
for (let i = 1; i <= 100; i++) {
  sum += i;
}
console.log(sum);
Вывод
5050

Счётчик может идти и в обратную сторону, и с любым шагом: for (let i = 10; i > 0; i -= 2) даёт 10, 8, 6, 4, 2.

Цикл while

while повторяет тело, пока условие верно. Он удобен, когда заранее неизвестно, сколько будет повторов. Например: сколько раз нужно удвоить единицу, чтобы получить больше тысячи?

JavaScript
let n = 1;
let steps = 0;

while (n <= 1000) {
  n *= 2;
  steps++;
}

console.log(n, steps);
Вывод
1024 10

Условие проверяется до каждого прохода. Если оно неверно с самого начала, тело не выполнится ни разу.

Цикл do … while проверяет условие после прохода, поэтому тело выполняется хотя бы один раз:

JavaScript
let attempts = 0;
do {
  attempts++;
  console.log("Попытка " + attempts);
} while (attempts < 3);
Вывод
Попытка 1
Попытка 2
Попытка 3
while — сначала проверка n <= 1000 да тело цикла нет после цикла тело может не выполниться ни разу do...while — сначала тело тело цикла attempts < 3 да нет после цикла тело выполнится хотя бы один раз
while сначала проверяет условие и, если оно сразу ложно, не выполняет тело ни разу, а do...while сначала выполняет тело и только потом проверяет условие.

Бесконечный цикл

Если условие никогда не станет ложным, цикл не закончится:

JavaScript
let i = 0;
while (i < 10) {
  console.log(i);
  // нет i++: i всегда 0, и цикл бесконечный
}

Бесконечный цикл на странице «вешает» вкладку браузера: она перестаёт отвечать, и браузер через некоторое время предложит её закрыть. В Node.js программу останавливает Ctrl+C в терминале. Прежде чем запускать цикл, проверьте, что в нём меняется то, от чего зависит условие.

Перебор массива: for...of

Массив — список значений в квадратных скобках (подробно — в уроке Массивы и методы map, filter, reduce). Перебрать его элементы по очереди проще всего циклом for...of:

JavaScript
const fruits = ["яблоко", "груша", "слива"];

for (const fruit of fruits) {
  console.log(fruit);
}
Вывод
яблоко
груша
слива

На каждой итерации в fruit оказывается следующий элемент. Номер элемента здесь не нужен, и ошибиться в границах счётчика невозможно. Строку for...of перебирает по символам: for (const ch of "JS") даст J, потом S.

Если номер всё же нужен — подойдёт обычный for. Номера элементов массива начинаются с нуля, а последний номер на единицу меньше длины fruits.length:

JavaScript
const fruits = ["яблоко", "груша", "слива"];

for (let i = 0; i < fruits.length; i++) {
  console.log(i + 1 + ". " + fruits[i]);
}
Вывод
1. яблоко
2. груша
3. слива

Частая ошибка — i <= fruits.length: на последнем шаге fruits[3] не существует, и в выводе появится undefined.

Есть ещё цикл for...in. Он перебирает не значения, а имена свойств объекта. Для массивов его не берут — только for...of. Как перебирать объекты, рассказано в уроке Объекты и JSON.

break и continue

Первое число больше 50, которое делится на 7:

JavaScript
for (let i = 51; i < 100; i++) {
  if (i % 7 === 0) {
    console.log("Нашлось: " + i);
    break;
  }
}
Вывод
Нашлось: 56

Только нечётные числа от 1 до 9:

JavaScript
for (let i = 1; i <= 9; i++) {
  if (i % 2 === 0) {
    continue;
  }
  console.log(i);
}
Вывод
1
3
5
7
9
continue — к следующей итерации for (let i = 1; i <= 9; i++) { if (i % 2 === 0) { continue; } console.log(i); пропускается } вывод: 1 3 5 7 9 break — выход из цикла for (let i = 51; i < 100; i++) { if (i % 7 === 0) { console.log("Нашлось: " + i); break; } } после цикла вывод: Нашлось: 56
continue пропускает остаток итерации: при чётном i вывод не выполняется, и цикл переходит к i++; break при i = 56 сразу завершает цикл, и следующие числа уже не проверяются.

Вложенные циклы

Цикл может стоять внутри другого цикла. Внутренний проходит целиком на каждой итерации внешнего. Так строится таблица умножения:

JavaScript
for (let i = 1; i <= 3; i++) {
  let row = "";
  for (let j = 1; j <= 4; j++) {
    row += String(i * j).padStart(4);
  }
  console.log(row);
}
Вывод
   1   2   3   4
   2   4   6   8
   3   6   9  12

padStart(4) дополняет строку пробелами слева до четырёх символов — так столбцы выравниваются. Во вложенных циклах счётчики называют по-разному (i и j), иначе внутренний цикл испортит значение внешнего.

Какой цикл выбрать

ЗадачаЦикл
Перебрать все элементы массива или символы строкиfor...of
Повторить известное число раз, нужен номерfor
Повторять, пока не выполнится условиеwhile
Выполнить хотя бы один раз, потом проверитьdo...while

У массивов есть и свои методы перебора — forEach, map, filter. Часто они заменяют цикл одной строкой; о них — в уроке о массивах.

Коротко

Проверьте себя

1. Сколько раз выполнится тело цикла for (let i = 0; i < 5; i++)?
2. Чем do...while отличается от while?
3. Что выведет программа?
JavaScript
for (let i = 1; i <= 5; i++) {
  if (i === 3) {
    break;
  }
  console.log(i);
}
4. Каким циклом удобнее всего перебрать все элементы массива?