MakeFirstStep· Frontend + ИИ

Урок 4 · JavaScript

Циклы

Показать 100 товаров на странице, пройти по всем буквам пароля, посчитать выручку за месяц, нарисовать таблицу — всё это «сделай одно и то же много раз». Писать одну и ту же строку сто раз никто не будет: для этого есть циклы. Сегодня вы научитесь их писать, останавливать и — что не менее важно — не допускать, чтобы они не остановились никогда.

  • Повторять действие через while, for и do..while и объяснять, как цикл идёт по шагам
  • Выбирать подходящий цикл под задачу
  • Управлять ходом цикла через break и continue
  • Перебирать строку по буквам с помощью for..of
  • Копить результат в переменной: сумма, счётчик, максимум, строка
  • Рисовать таблицы и фигуры вложенными циклами и узнавать бесконечный цикл
Как работать с этой страницей

Весь код на тёмном фоне с кнопкой ▶ Запустить — живой. Меняйте его прямо здесь и сразу смотрите результат в консоли под ним. Сломали — нажмите ↺ Сброс. Подсказки к задачам спрятаны: сначала попробуйте сами, открывайте подсказку, только если застряли. Сегодня мы пользуемся только тем, что уже знаем: переменными, типами и условиями. Функций и массивов пока нет — они на уроках 5 и 6.

01 Зачем нужны циклы. Цикл while

Представьте, что вы встречаете пятерых гостей на пороге MakeFirstStep. Без циклов код выглядит так:

Без цикла: копируем строки · Ctrl + Enter
console.log("Гость №1, добро пожаловать!");
console.log("Гость №2, добро пожаловать!");
console.log("Гость №3, добро пожаловать!");
console.log("Гость №4, добро пожаловать!");
console.log("Гость №5, добро пожаловать!");

Пять строк — ещё терпимо. А если гостей 500? А если их число заранее неизвестно? Здесь и приходит на помощь цикл — конструкция, которая повторяет блок кода, пока выполняется условие. Самый простой цикл — while («пока»):

С циклом while · Ctrl + Enter
let i = 1;                 // 1. старт: счётчик начинается с 1
while (i <= 5) {           // 2. условие: повторяем, пока оно true
  console.log(`Гость №${i}, добро пожаловать!`);
  i++;                     // 3. шаг: меняем счётчик
}
console.log("Все гости встречены");
Аналогия из жизни

Вы раздаёте оши палав на свадьбе. Правило простое: пока в казане есть плов — накладываем ещё одну тарелку. Перед каждой тарелкой вы заглядываете в казан (проверяете условие). Плов есть — накладываете (выполняете тело). Казан пуст — закончили. Сколько будет тарелок, вы заранее не знаете: это зависит от казана.

Как работает while — по шагам

  1. Проверка условия. JavaScript вычисляет выражение в скобках после while. Это то же самое выражение, что и в if: true или false.
  2. Если true — выполняется всё, что в фигурных скобках. Это тело цикла.
  3. Возврат к шагу 1. Дошли до закрывающей скобки — снова проверяем условие.
  4. Если false — цикл заканчивается, программа идёт дальше, к строке после }.

Один проход по телу называется итерацией (или «кругом»). Вот что происходит в нашем примере:

Кругi перед проверкойi <= 5?Что выводитсяi после i++
11trueГость №12
22trueГость №23
33trueГость №34
44trueГость №45
55trueГость №56
—6falseцикл закончился, идём к строке «Все гости встречены»
Тело цикла
Код в фигурных скобках, который повторяется.
Условие
Выражение, которое проверяется перед каждым кругом. true — крутимся дальше, false — выходим.
Итерация
Один круг цикла: один проход по телу.
Счётчик
Переменная, которая меняется от круга к кругу и в итоге делает условие ложным. Обычно её называют i.
Напоминание: короткие записи

i++ — то же самое, что i = i + 1. i-- — уменьшить на 1. i += 2 — прибавить 2, money -= 6 — вычесть 6. Эти записи мы будем встречать в каждом цикле.

while, когда число кругов заранее неизвестно

Главная сила while — ситуации «делай, пока не случится что-то». Например, пока хватает денег на чай:

Можно редактировать · Ctrl + Enter
let money = 20;          // сомони в кошельке
const teaPrice = 6;      // цена чайника чая

while (money >= teaPrice) {
  money -= teaPrice;
  console.log(`Выпили чай. Осталось: ${money} сомони`);
}
console.log("Денег на чай больше нет");

Сколько чайников получится — заранее не видно, цикл сам посчитал. Если же число повторений известно сразу («ровно 5 гостей»), удобнее другая запись — for, о ней в следующем разделе.

Частые ошибки

1. Если условие ложно с самого начала, тело не выполнится ни разу — и это нормально, просто ничего не выведется. 2. Если забыть изменить счётчик (i++), условие навсегда останется истинным и цикл будет вращаться вечно — это бесконечный цикл. Мы разберём его отдельно в разделе 08, не пугайтесь.

Условие ложно сразу: тело не выполняется · Ctrl + Enter
let n = 10;
while (n < 5) {
  console.log("Сюда мы не попадём");
  n++;
}
console.log("Конец, n =", n);   // → Конец, n = 10

Читать подробнее: learn.javascript.ru — Циклы while и for · MDN — while

Практика: закрепляем

Три маленьких цикла while: считаем вперёд, назад и копим деньги.

ЗАДАЧА 1.1

Встреча гостей

лёгкая

С помощью while выведите приглашения для четырёх студентов: Студент №1, проходите в аудиторию и так далее до четвёртого.

Можно редактировать · Ctrl + Enter
let i = 1;
// ваш цикл while здесь
Ожидаемый результат
Студент №1, проходите в аудиторию
Студент №2, проходите в аудиторию
Студент №3, проходите в аудиторию
Студент №4, проходите в аудиторию
Подсказка 1

Условие: пока i не больше 4 — while (i <= 4).

Подсказка 2

Внутри тела — console.log(`Студент №${i}, проходите в аудиторию`) и, обязательно, i++.

ЗАДАЧА 1.2

Обратный отсчёт

лёгкая

Перед стартом экзамена объявляют отсчёт: 5, 4, 3, 2, 1 — и после цикла слово Начали!. Счётчик должен уменьшаться.

Можно редактировать · Ctrl + Enter
let seconds = 5;
// цикл while здесь

console.log("Начали!");
Ожидаемый результат
5
4
3
2
1
Начали!
Подсказка 1

Условие — пока seconds больше нуля: seconds > 0.

Подсказка 2

Сначала выводим значение, потом уменьшаем: seconds--. Вывод «Начали!» стоит после закрывающей скобки цикла.

ЗАДАЧА 1.3

Копилка на телефон

средняя

Вы копите на наушники за 30 сомони. Каждый день откладываете по 5 сомони. Выводите по одной строке на каждый день: День 1: накоплено 5 сомони, пока сумма не достигнет цели. Заведите две переменные — day и saved.

Можно редактировать · Ctrl + Enter
const goal = 30;
let saved = 0;
let day = 0;
// цикл: пока saved меньше goal
Ожидаемый результат
День 1: накоплено 5 сомони
День 2: накоплено 10 сомони
День 3: накоплено 15 сомони
День 4: накоплено 20 сомони
День 5: накоплено 25 сомони
День 6: накоплено 30 сомони
Подсказка 1

В цикле меняются две переменные: day++ и saved += 5. Условие следит за saved.

Подсказка 2

Сначала увеличьте day и saved, потом выведите строку — тогда в ней сразу правильные числа.

02 Цикл for

В цикле while три важные части — старт, условие и шаг — разбросаны по коду: старт выше цикла, шаг в конце тела. Легко что-то забыть. Цикл for собирает всё это в одну строку:

Можно редактировать · Ctrl + Enter
for (let i = 1; i <= 5; i++) {
  console.log(`Гость №${i}, добро пожаловать!`);
}

Результат тот же, что у while в прошлом разделе, но кода меньше и все три части видны сразу.

for (let i = 1; i <= 5; i++) { console.log(i); }
Три части в скобках разделяются точками с запятой
Аналогия из жизни

Маршрутка №8 едет по остановкам. Заголовок for — это ответ на три вопроса: на какой остановке сел (let i = 1), до какой едешь (i <= 5) и как едешь — по одной остановке или через одну (i++). Тело цикла — то, что ты делаешь на каждой остановке: смотришь в окно, выходишь, оплачиваешь.

В каком порядке всё выполняется

  1. Старт let i = 1 выполняется один раз, самым первым.
  2. Условие i <= 5 проверяется перед каждым кругом. false — выход из цикла.
  3. Тело выполняется целиком.
  4. Шаг i++ выполняется после тела. Затем снова шаг 2.

Разные варианты заголовка

Меняя три части, можно считать как угодно: с нуля, с шагом, назад.

Что нужноЗаголовокЗначения i
от 1 до 5for (let i = 1; i <= 5; i++)1 2 3 4 5
от 0 до 4 (пять кругов)for (let i = 0; i < 5; i++)0 1 2 3 4
с шагом 2for (let i = 2; i <= 10; i += 2)2 4 6 8 10
назадfor (let i = 5; i >= 1; i--)5 4 3 2 1
Можно редактировать · Ctrl + Enter
console.log("--- с шагом 5 ---");
for (let i = 0; i <= 20; i += 5) {
  console.log(i);
}

console.log("--- назад ---");
for (let i = 3; i >= 1; i--) {
  console.log(`Осталось ${i}`);
}
Совет: while или for?

Знаете заранее, сколько кругов («5 гостей», «от 1 до 100») — берите for. Крутиться нужно «пока не случится что-то» (хватает денег, не закончился ввод) — берите while. Любой for можно переписать на while и наоборот: это вопрос удобства.

Ловушка: на единицу ошибся

Самая частая ошибка в циклах — «ошибка на единицу» (off-by-one). Разница между i < 5 и i <= 5 — это целый лишний круг. Если считаете с нуля, пишите <; если с единицы — <=. И всегда проверяйте первое и последнее значение.

Можно редактировать · Ctrl + Enter
for (let i = 1; i < 5; i++) {
  console.log(`Урок ${i}`);   // 5-й урок потерялся!
}

Переменная цикла живёт только внутри

Этот код выдаст ошибку · Ctrl + Enter
for (let i = 1; i <= 3; i++) {
  console.log(i);
}
console.log(i);   // ✖ i не существует вне цикла

Это нормально и даже удобно: каждый цикл имеет собственную i, и циклы друг другу не мешают. Если значение нужно после цикла, объявляйте переменную до него. Почему так устроено — расскажем на уроке про функции.

Читать подробнее: learn.javascript.ru — Цикл for · MDN — for

Практика: закрепляем

Меняем стартовое значение, шаг и направление.

ЗАДАЧА 2.1

Самбуса по 5 сомони

лёгкая

Самбуса стоит 5 сомони. Выведите стоимость для 1, 2, 3, 4 и 5 штук: 3 шт. — 15 сомони. Используйте цикл for.

Можно редактировать · Ctrl + Enter
const price = 5;
// for ...
Ожидаемый результат
1 шт. — 5 сомони
2 шт. — 10 сомони
3 шт. — 15 сомони
4 шт. — 20 сомони
5 шт. — 25 сомони
Подсказка 1

Пусть счётчик qty идёт от 1 до 5 включительно: for (let qty = 1; qty <= 5; qty++).

Подсказка 2

Стоимость считается прямо в строке: `${qty} шт. — ${qty * price} сомони`.

ЗАДАЧА 2.2

Найдите баг: пропавший урок

средняя

Цикл должен вывести уроки с 1 по 5, но выводит что-то другое. Запустите, посмотрите на результат и исправьте заголовок цикла.

Можно редактировать · Ctrl + Enter
for (let i = 0; i < 5; i++) {
  console.log(`Урок ${i}`);
}
Ожидаемый результат после исправления
Урок 1
Урок 2
Урок 3
Урок 4
Урок 5
Подсказка 1

С какого значения начинается счётчик сейчас и с какого должен?

Подсказка 2

Можно поменять две части: старт на 1 и условие на <= 5. Либо оставить i < 5, но выводить i + 1 — подойдёт любой способ, только не оба сразу.

ЗАДАЧА 2.3

Предскажите вывод и допишите

средняя

Сначала не запуская код, запишите в тетрадь, что выведут два цикла. Потом запустите и сверьтесь. Затем допишите третий цикл, который выведет C10, C7, C4, C1 (идём от 10 вниз с шагом 3).

Можно редактировать · Ctrl + Enter
for (let i = 3; i > 0; i--) {
  console.log("A" + i);
}

for (let i = 0; i < 10; i += 4) {
  console.log("B" + i);
}

// третий цикл здесь
Ожидаемый результат
A3
A2
A1
B0
B4
B8
C10
C7
C4
C1
Подсказка 1

Старт — 10, условие — пока i не меньше 1 (i >= 1).

Подсказка 2

Шаг «вниз на 3» записывается как i -= 3.

03 Цикл do..while

У while есть брат-близнец: do..while («делай, пока»). Разница одна, но важная: условие проверяется после тела, поэтому тело выполнится минимум один раз, даже если условие ложно с самого начала.

Можно редактировать · Ctrl + Enter
let attempt = 0;

do {
  attempt++;
  console.log(`Попытка входа №${attempt}`);
} while (attempt < 3);

Обратите внимание на точку с запятой после while (…) — в do..while она нужна. Теперь сравните оба цикла, когда условие ложно сразу:

while против do..while · Ctrl + Enter
let cups = 0;

while (cups > 0) {
  console.log("while: тело выполнилось");
}

do {
  console.log("do..while: тело выполнилось");
} while (cups > 0);
Аналогия из жизни

В чайхане чайник с чаем приносят сразу, не спрашивая, а потом интересуются: «Ещё?». Это do..while: сначала действие, потом вопрос. В другом заведении сперва спросят: «Принести чай?» — и только после «да» принесут. Это while: сначала проверка, потом действие.

whiledo..while
Когда проверяется условиедо телапосле тела
Минимум кругов01
Точка с запятой после условияне нужнанужна
Когда выбиратьпочти всегдадействие обязательно нужно сделать хотя бы раз: показать меню, снять деньги, попросить ввод
Совет

do..while встречается намного реже, чем for и while. Знать его нужно, чтобы не растеряться в чужом коде, но в своих программах обычно хватает первых двух.

Читать подробнее: MDN — do...while · learn.javascript.ru — Цикл do..while

Практика: закрепляем

Сравниваем два цикла и пишем банкомат.

ЗАДАЧА 3.1

while против do..while

лёгкая

Предскажите, что выведет код: сколько раз выполнится каждое тело и чему равно n в самом конце. Впишите в prediction все строки вывода по порядку (если какой-то цикл не выполнится ни разу, его строк там нет) и запустите.

Можно редактировать · Ctrl + Enter
const log = [];   // сюда код собирает «вывод»
let n = 10;
while (n < 5) {
  log.push(`while: n = ${n}`);
  n++;
}
do {
  log.push(`do..while: n = ${n}`);
  n++;
} while (n < 5);
log.push(`Итог: n = ${n}`);

const prediction = [];   // ваш прогноз: строки вывода по порядку, например ["do: n = 1", …]
console.log(log.join("|") === prediction.join("|") ? "Верно!" : "Не угадали, подумайте ещё");
Ожидаемый результат
Верно!
Подсказка 1

Условие n < 5 при n = 10 ложно. Что это значит для while?

Подсказка 2

do..while всегда делает один круг до проверки. После него n становится 11, и проверка уже не пропускает второй круг.

ЗАДАЧА 3.2

Банкомат

средняя

На счету 100 сомони. Банкомат выдаёт по 30 сомони за раз. Напишите цикл do..while: выдайте купюру, выведите строку Выдано 30 сомони, остаток: …, и повторяйте, пока остаток не меньше 30. В конце выведите итоговый остаток.

Можно редактировать · Ctrl + Enter
let balance = 100;
// do { ... } while (...);

console.log(`Итоговый остаток: ${balance}`);
Ожидаемый результат
Выдано 30 сомони, остаток: 70
Выдано 30 сомони, остаток: 40
Выдано 30 сомони, остаток: 10
Итоговый остаток: 10
Подсказка 1

В теле: balance -= 30; и console.log. Условие продолжения — balance >= 30.

Подсказка 2

Не забудьте точку с запятой после while (balance >= 30). Проверьте себя: при остатке 10 круг не повторяется.

04 break и continue

Иногда цикл нужно прервать раньше срока или пропустить один круг. Для этого есть два слова.

  • break — выйти из цикла совсем. Программа продолжается со строки после цикла.
  • continue — пропустить остаток текущего круга и перейти к следующему.
break: нашли — выходим · Ctrl + Enter
for (let i = 1; i <= 10; i++) {
  if (i === 4) {
    console.log("Нашли нужную остановку! Выходим");
    break;
  }
  console.log(`Проезжаем остановку №${i}`);
}
console.log("Цикл закончился");
Аналогия из жизни

Вы ищете свободный стол в чайхане и идёте вдоль рядов. Нашли — break: дальше не ищете, садитесь. А continue — это «этот стол занят, не останавливаюсь, иду к следующему». Поиск продолжается, но один стол вы просто пропустили.

Остаток от деления: оператор %

Для примера с continue нам понадобится оператор % — остаток от деления. 7 % 3 — это остаток от деления 7 на 3, то есть 1. Число чётное, если остаток от деления на 2 равен нулю.

Можно редактировать · Ctrl + Enter
console.log(7 % 3);    // → 1   (7 = 3 + 3 + остаток 1)
console.log(10 % 5);   // → 0   (делится нацело)
console.log(9 % 2);    // → 1   (нечётное)
console.log(8 % 2);    // → 0   (чётное)
continue: пропускаем круг · Ctrl + Enter
for (let i = 1; i <= 8; i++) {
  if (i % 2 === 0) {
    continue;           // чётные пропускаем
  }
  console.log(`Нечётное число: ${i}`);
}
breakcontinue
Что делаетПолностью выходит из циклаПропускает остаток круга
Что дальшеКод после циклаСледующий круг (шаг i++ и проверка условия)
Типичный случайИскали что-то и нашлиЧасть значений обрабатывать не нужно

Приём: while (true) и break

Бывает, что заранее непонятно, когда остановиться. Тогда пишут условие true (цикл «навсегда») и выходят через break, когда пришло время. Это единственный случай, когда «вечный» цикл — осознанный, потому что выход у него предусмотрен.

Можно редактировать · Ctrl + Enter
let n = 1;
while (true) {
  n *= 2;               // удваиваем
  console.log(n);
  if (n > 50) {
    break;              // выход предусмотрен
  }
}
console.log("Остановились на", n);
Ловушка: continue в while

В for шаг i++ выполняется сам. А в while он стоит в теле — и если continue сработает раньше него, счётчик не изменится, условие останется истинным, цикл зависнет. Этот код запускать не нужно:

Опасно: не запускайте, это бесконечный цикл
let i = 0;
while (i < 5) {
  if (i === 2) {
    continue;      // перескочили i++ — i навсегда останется равным 2
  }
  console.log(i);
  i++;
}

Решение: менять счётчик до continue или использовать for. Подробнее о бесконечных циклах — в разделе 08.

Читать подробнее: MDN — break · MDN — continue · learn.javascript.ru — break и continue

Практика: закрепляем

Выходим из цикла вовремя, пропускаем лишнее и ловим хитрую ошибку.

ЗАДАЧА 4.1

Хватит ли денег на самбусу

лёгкая

В кошельке 100 сомони, самбуса стоит 15. Цикл for пробует купить самбусы с номерами от 1 до 10. Если общая стоимость i * 15 превышает 100 — выведите Денег больше нет и выйдите из цикла через break. Иначе выведите Самбуса №…: всего … сомони.

Можно редактировать · Ctrl + Enter
const wallet = 100;
const price = 15;
// for (let i = 1; i <= 10; i++) { ... }
Ожидаемый результат
Самбуса №1: всего 15 сомони
Самбуса №2: всего 30 сомони
Самбуса №3: всего 45 сомони
Самбуса №4: всего 60 сомони
Самбуса №5: всего 75 сомони
Самбуса №6: всего 90 сомони
Денег больше нет
Подсказка 1

Сначала проверка: if (i * price > wallet). Внутри неё — console.log("Денег больше нет") и break.

Подсказка 2

Строку про самбусу пишите после if: до неё дойдут только те круги, где денег хватило.

ЗАДАЧА 4.2

Без чисел, кратных трём

лёгкая

Выведите числа от 1 до 10, но числа, которые делятся на 3, пропустите с помощью continue.

Можно редактировать · Ctrl + Enter
for (let i = 1; i <= 10; i++) {
  // пропустите кратные трём
  console.log(i);
}
Ожидаемый результат
1
2
4
5
7
8
10
Подсказка 1

Число делится на 3 нацело, если остаток от деления на 3 равен нулю: i % 3 === 0.

Подсказка 2

Проверка с continue должна стоять перед console.log, иначе число успеет вывестись.

ЗАДАЧА 4.3

Найдите баг: цикл останавливается сразу

средняя

Цикл должен вывести числа от 1 до 5 и остановиться на пятёрке. Но он выводит только единицу. Запустите, подумайте, чем отличаются = и === (вспомните урок про условия), и исправьте одну ошибку.

Можно редактировать · Ctrl + Enter
for (let i = 1; i <= 10; i++) {
  console.log(i);
  if (i = 5) {
    break;
  }
}
Ожидаемый результат после исправления
1
2
3
4
5
Подсказка 1

Один знак = — это присваивание, а не сравнение. Условие i = 5 записывает в i число 5, а результат (5) считается «истиной».

Подсказка 2

Для сравнения нужно три знака: i === 5.

05 Перебор строки: for..of

Цикл можно запускать не только по числам, но и по буквам строки. Для этого есть удобная форма for..of («для каждого … из …»):

Можно редактировать · Ctrl + Enter
for (const letter of "Душанбе") {
  console.log(letter);
}

На каждом круге в переменную letter попадает следующая буква. Не нужно ни счётчика, ни условия, ни шага — JavaScript сам дойдёт до конца строки. Пишем const, потому что на каждом круге создаётся новая переменная, а внутри круга мы её не меняем.

Аналогия из жизни

Тасбех (чётки): вы перебираете бусины по одной, от первой до последней. for..of — «для каждой бусины делай то-то». Вам не важно, какая она по номеру, вы просто берёте следующую, пока нить не закончится.

Тот же перебор через обычный for

Каждая буква в строке имеет номер — индекс. Нумерация начинается с нуля. Получить букву по номеру можно через квадратные скобки: city[0]. Количество букв хранится в city.length. Поэтому последний индекс — length - 1.

Можно редактировать · Ctrl + Enter
const city = "Хорог";
console.log(city.length);   // → 5
console.log(city[0]);       // → Х
console.log(city[4]);       // → г

for (let i = 0; i < city.length; i++) {
  console.log(`${i}: ${city[i]}`);
}

Когда нужен только сам символ — берём for..of, это проще. Когда нужен ещё и номер (например, сравнить первую и последнюю букву) — берём обычный for с индексом.

Типичные задачи на строки

Посчитать, сколько раз встречается буква:

Можно редактировать · Ctrl + Enter
const word = "самбуса";
let count = 0;
for (const ch of word) {
  if (ch === "с") {
    count++;
  }
}
console.log(`Букв «с»: ${count}`);   // → Букв «с»: 2

Собрать новую строку — например, перевернуть слово. Каждую новую букву приписываем слева к уже собранному:

Можно редактировать · Ctrl + Enter
let reversed = "";
for (const ch of "оши") {
  reversed = ch + reversed;
  console.log(`взяли «${ch}» → ${reversed}`);
}
console.log(reversed);   // → ишо

А что с массивами? Маленький взгляд вперёд

Точно так же for..of умеет перебирать список значений — он называется массив и записывается в квадратных скобках. Массивам посвящён весь следующий урок, а пока просто посмотрите — форма цикла та же:

Взгляд вперёд: массив (подробно на уроке 6) · Ctrl + Enter
for (const dish of ["плов", "самбуса", "курутоб"]) {
  console.log(`В меню: ${dish}`);
}
НужноБерём
Повторить действие N раз, перебрать числаfor
Повторять, пока выполняется условиеwhile
Каждый символ строки (номер не нужен)for..of
Символы строки и их номераfor с i и text[i]
Две ловушки

1. Строки в JavaScript нельзя изменить «по месту»: нельзя заменить одну букву через word[0] = "К". Всегда собирайте новую строку. 2. for..of работает только по тому, что можно перебрать (строки, массивы). Число перебрать нельзя.

Этот код выдаст ошибку · Ctrl + Enter
const word = "Душанбе";
word[0] = "К";             // ✖ строку нельзя менять по символам
Этот код выдаст ошибку · Ctrl + Enter
for (const digit of 12345) {   // ✖ число не перебирается
  console.log(digit);
}
Знаете ли вы?

Для повторения строки есть готовый метод: "*".repeat(5) даёт *****. В реальных проектах его используют часто. Но пока мы учимся — собираем строки циклами сами: так вы поймёте, как это работает.

Читать подробнее: MDN — for...of · learn.javascript.ru — Строки

Практика: закрепляем

Работаем с буквами: выводим, считаем, переворачиваем и проверяем на палиндром.

ЗАДАЧА 5.1

Город по буквам

лёгкая

Выведите каждую букву слова Хуҷанд в отдельной строке в формате Буква: Х. Используйте for..of.

Можно редактировать · Ctrl + Enter
const city = "Хуҷанд";
// for (const ... of ...)
Ожидаемый результат
Буква: Х
Буква: у
Буква: ҷ
Буква: а
Буква: н
Буква: д
Подсказка 1

Заголовок: for (const ch of city).

Подсказка 2

В теле: console.log(`Буква: ${ch}`).

ЗАДАЧА 5.2

Сколько раз «а»

лёгкая

Посчитайте, сколько раз в тексте встречается маленькая буква а. Заведите счётчик, переберите текст через for..of и увеличивайте счётчик, когда нужная буква найдена.

Можно редактировать · Ctrl + Enter
const text = "Душанбе — столица Таджикистана";
// счётчик, цикл, вывод
Ожидаемый результат
Букв «а»: 5
Подсказка 1

Перед циклом: let count = 0;. Внутри: if (ch === "а") { count++; }.

Подсказка 2

Вывод — после цикла: console.log(`Букв «а»: ${count}`). Большая «Т» и латинская «a» — другие символы, их мы не считаем.

ЗАДАЧА 5.3

Слово наоборот

средняя

Переверните слово MakeFirstStep с помощью for..of и пустой строки-накопителя. Выведите результат.

Можно редактировать · Ctrl + Enter
const word = "MakeFirstStep";
// let result = "";
Ожидаемый результат
petStsriFekaM
Подсказка 1

Каждую следующую букву надо добавлять перед уже собранной строкой: result = ch + result.

Подсказка 2

Вывод — после цикла, одной строкой: console.log(result).

ЗАДАЧА 5.4

Палиндром или нет

сложная

Палиндром читается одинаково слева направо и справа налево («шалаш»). Проверьте слово обычным for с индексом: сравнивайте букву с номером i и букву с номером word.length - 1 - i. Заведите переменную isPalindrome = true и, найдя несовпадение, поставьте false и выйдите через break. Сейчас в коде слово «Душанбе» — для него должно получиться «не палиндром». Затем подставьте «шалаш» и убедитесь, что код определяет палиндром.

Можно редактировать · Ctrl + Enter
const word = "Душанбе";
let isPalindrome = true;
// цикл for по индексам

console.log(`${word} — ${isPalindrome ? "палиндром" : "не палиндром"}`);
Ожидаемый результат
Душанбе — не палиндром
Подсказка 1

Сравнение: if (word[i] !== word[word.length - 1 - i]). Для слова из 5 букв это пары (0 и 4), (1 и 3), (2 и 2).

Подсказка 2

Внутри if: isPalindrome = false; break;. Цикл можно запускать i < word.length: лишние сравнения вторую половину слова просто подтвердят.

06 Счётчики и накопители

Почти любой цикл в реальной программе что-то накапливает: общую сумму чека, число подходящих товаров, самую высокую цену, итоговую строку. Для этого есть универсальный приём:

  1. До цикла заводим переменную с начальным значением (накопитель).
  2. В теле цикла обновляем её на каждом круге.
  3. После цикла используем итог.
Аналогия из жизни

Касса в магазине на Зелёном базаре. Утром в ней 0 сомони — это старт. Каждый покупатель кладёт деньги — это тело цикла. Вечером кассир подсчитывает итог — это код после цикла. Касса не обнуляется после каждого покупателя: иначе вечером вы увидели бы только деньги последнего.

Что считаемСтартНа каждом круге
Суммаlet sum = 0sum += x
Произведениеlet product = 1product *= x
Счётчик «сколько подходит»let count = 0if (условие) { count++ }
Максимумlet best = 0if (x > best) { best = x }
Строкаlet line = ""line += "текст"

Сумма

Копилка: каждый день на 10 сомони больше · Ctrl + Enter
let total = 0;                       // старт — пусто

for (let day = 1; day <= 5; day++) {
  total += day * 10;                 // в день N откладываем N × 10
  console.log(`День ${day}: +${day * 10}, всего ${total}`);
}

console.log(`Накоплено: ${total} сомони`);

Произведение

Для умножения старт — единица: ноль «съест» всё произведение. Факториал числа (4! = 1 · 2 · 3 · 4) — классика:

Можно редактировать · Ctrl + Enter
let product = 1;
for (let i = 1; i <= 4; i++) {
  product *= i;
}
console.log(`4! = ${product}`);   // → 4! = 24

Счётчик «сколько подходит»

Можно редактировать · Ctrl + Enter
let count = 0;
for (let n = 1; n <= 50; n++) {
  if (n % 7 === 0) {
    count++;
  }
}
console.log(`Чисел, кратных 7, до 50: ${count}`);   // → 7

Максимум и среднее

В какой день прибыль была больше всего · Ctrl + Enter
let best = 0;       // лучшая прибыль
let bestDay = 0;    // в какой день она была
let sum = 0;

for (let day = 1; day <= 9; day++) {
  const profit = day * (10 - day);   // условная формула прибыли
  sum += profit;
  if (profit > best) {
    best = profit;
    bestDay = day;
  }
}

console.log(`Лучший день: ${bestDay}, прибыль ${best}`);
console.log(`Среднее: ${sum / 9}`);

Строка

Накопителем может быть и строка. Во вложенных циклах (раздел 07) этот приём нам очень пригодится:

Можно редактировать · Ctrl + Enter
let line = "";
for (let i = 1; i <= 5; i++) {
  line += i + " ";
}
console.log(line);   // → 1 2 3 4 5
Ловушки накопителей

1. Накопитель объявлен внутри цикла — на каждом круге он обнуляется. 2. Неверный старт: для суммы 0, для произведения 1. 3. Накопитель выводится внутри цикла, а нужен только итог — тогда строк на экране слишком много.

Ошибка: накопитель сбрасывается каждый круг · Ctrl + Enter
for (let i = 1; i <= 3; i++) {
  let total = 0;           // ← каждый круг начинаем с нуля!
  total += i;
  console.log(`total = ${total}`);   // 1, 2, 3 вместо 1, 3, 6
}
ИИ-подсказка

Когда ИИ предлагает в ответ «красивое» решение задачи про сумму или поиск максимума, часто видите reduce, Math.max и прочее, чего мы пока не проходили. Если нужно решение именно через цикл, прямо напишите в промпте: «только цикл for, без методов массивов и без функций».

Читать подробнее: MDN — Циклы и итерация · learn.javascript.ru — Циклы

Практика: закрепляем

Сумма, среднее, произведение и первая «финансовая» задача.

ЗАДАЧА 6.1

Сумма от 1 до 10

лёгкая

Сложите все целые числа от 1 до 10 и выведите результат.

Можно редактировать · Ctrl + Enter
// let sum = 0;
Ожидаемый результат
Сумма: 55
Подсказка 1

Цикл for (let i = 1; i <= 10; i++), внутри sum += i.

Подсказка 2

Вывод — один раз, после цикла: console.log(`Сумма: ${sum}`).

ЗАДАЧА 6.2

Выручка за неделю

средняя

Магазин на Шохмансуре в день с номером d зарабатывает d * 20 сомони (день 1 — 20, день 2 — 40 и так далее до 7). Посчитайте выручку за неделю и среднюю выручку за день.

Можно редактировать · Ctrl + Enter
// накопитель, цикл по дням 1..7, два вывода
Ожидаемый результат
Итого: 560 сомони
В среднем за день: 80 сомони
Подсказка 1

Накапливаем total += day * 20. Среднее — это итог, поделённый на количество дней (7).

Подсказка 2

Оба вывода — после цикла. 20 + 40 + … + 140 = 560, и 560 / 7 = 80.

ЗАДАЧА 6.3

Найдите баг: нулевой факториал

средняя

Программа должна вывести 5! = 120, но выводит ноль. Найдите причину и исправьте одну строку.

Можно редактировать · Ctrl + Enter
let result = 0;
for (let i = 1; i <= 5; i++) {
  result *= i;
}
console.log(`5! = ${result}`);
Ожидаемый результат после исправления
5! = 120
Подсказка 1

Любое число, умноженное на ноль, — ноль. С чего должен стартовать накопитель при умножении?

Подсказка 2

Замените let result = 0 на let result = 1.

ЗАДАЧА 6.4

Когда удвоится вклад

сложная

Вы положили в банк 1000 сомони под 10% годовых. Каждый год сумма умножается на 1.1. Через сколько полных лет вклад станет не меньше 2000? Используйте цикл while и счётчик лет. В конце выведите число лет и итоговую сумму, округлённую до целого функцией Math.round(...).

Можно редактировать · Ctrl + Enter
let balance = 1000;
let years = 0;
// пока balance меньше 2000
Ожидаемый результат
Вклад удвоится через 8 лет: 2144 сомони
Подсказка 1

Условие — balance < 2000. В теле: balance *= 1.1; и years++;.

Подсказка 2

Вывод после цикла: `Вклад удвоится через ${years} лет: ${Math.round(balance)} сомони`. Сумма хранится с дробной частью, а округляем только при выводе.

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

Внутри цикла может быть другой цикл. Это называется вложенными циклами. Они нужны везде, где есть «двойной» перебор: дни и пары в расписании, строки и столбцы в таблице, ряды и места в зале.

Расписание: дни × пары · Ctrl + Enter
for (let day = 1; day <= 2; day++) {
  for (let lesson = 1; lesson <= 3; lesson++) {
    console.log(`День ${day}, пара ${lesson}`);
  }
}
Аналогия из жизни

Часы. Часовая стрелка делает один шаг, а минутная за это время обходит весь циферблат — 60 шагов. Внешний цикл — часовая стрелка, внутренний — минутная. Пока внешний делает один круг, внутренний успевает пройти все свои круги от начала до конца.

Как это выполняется

  1. Внешний цикл начинает круг: day = 1.
  2. Внутренний цикл запускается с самого начала и проходит все свои круги: lesson = 1, 2, 3.
  3. Внутренний закончился. Внешний делает шаг: day = 2.
  4. Внутренний снова запускается с нуля и снова проходит все круги.
ШагdaylessonВывод
111День 1, пара 1
212День 1, пара 2
313День 1, пара 3
421День 2, пара 1
522День 2, пара 2
623День 2, пара 3

Всего тело внутреннего цикла выполнилось 2 × 3 = 6 раз. Правило: число выполнений тела = круги внешнего × круги внутреннего.

Рисуем фигуры

console.log всегда переводит строку, поэтому нарисовать ряд символов в одной строке напрямую нельзя. Решение — собрать всю строку в накопитель внутренним циклом, а вывести её после внутреннего цикла:

Прямоугольник 3 × 5 · Ctrl + Enter
for (let row = 1; row <= 3; row++) {
  let line = "";                       // новая пустая строка для каждой строки
  for (let col = 1; col <= 5; col++) {
    line += "*";
  }
  console.log(line);                   // выводим готовую строку
}

Чтобы получить треугольник, достаточно, чтобы внутренний цикл зависел от внешнего: в строке номер row — ровно row символов.

Треугольник · Ctrl + Enter
for (let row = 1; row <= 4; row++) {
  let line = "";
  for (let col = 1; col <= row; col++) {
    line += "#";
  }
  console.log(line);
}

И, наконец, таблица умножения: в клетке стоит произведение номера строки и номера столбца.

Таблица умножения 3 × 3 · Ctrl + Enter
for (let row = 1; row <= 3; row++) {
  let line = "";
  for (let col = 1; col <= 3; col++) {
    line += row * col + " ";
  }
  console.log(line);
}
Ловушки вложенных циклов

1. Накопитель строки нужно обнулять для каждой строки — то есть объявлять между внешним и внутренним циклом, как let line = "" выше. 2. Не называйте обе переменные одинаково: используйте i и j или понятные row и col. 3. break выходит только из внутреннего цикла — внешний продолжает работать.

break во внутреннем цикле · Ctrl + Enter
for (let day = 1; day <= 3; day++) {
  for (let lesson = 1; lesson <= 3; lesson++) {
    if (day === 2 && lesson === 2) {
      break;            // прервали только пары второго дня
    }
    console.log(`День ${day}, пара ${lesson}`);
  }
}
Совет: сколько это работает

Вложенный цикл 1000 × 1000 — это миллион выполнений тела, компьютер справляется за долю секунды. Но тройной цикл на 10 000 × 10 000 × 10 000 уже может «подвесить» страницу. Чем глубже вложенность, тем осторожнее нужно быть.

Практика: закрепляем

Квадраты, места в зале, треугольники и шахматная доска.

ЗАДАЧА 7.1

Квадрат из решёток

лёгкая

Нарисуйте квадрат 4 × 4 из символов #.

Можно редактировать · Ctrl + Enter
// два вложенных цикла
Ожидаемый результат
####
####
####
####
Подсказка 1

Внешний цикл — четыре строки, внутренний — четыре символа в каждой.

Подсказка 2

Между циклами: let line = "";. После внутреннего цикла: console.log(line);.

ЗАДАЧА 7.2

Места в кинозале

лёгкая

В зале 2 ряда по 3 места. Выведите все места в формате Ряд 1, место 1.

Можно редактировать · Ctrl + Enter
// for по рядам, внутри for по местам
Ожидаемый результат
Ряд 1, место 1
Ряд 1, место 2
Ряд 1, место 3
Ряд 2, место 1
Ряд 2, место 2
Ряд 2, место 3
Подсказка 1

Внешний цикл по row от 1 до 2, внутренний по seat от 1 до 3.

Подсказка 2

Вывод — в теле внутреннего цикла: console.log(`Ряд ${row}, место ${seat}`).

ЗАДАЧА 7.3

Лесенка

средняя

Нарисуйте «лесенку» высотой 5: в первой строке одна звёздочка, во второй две и так далее. Символ вынесите в переменную symbol.

Можно редактировать · Ctrl + Enter
const symbol = "*";
const height = 5;
Ожидаемый результат
*
**
***
****
*****
Подсказка 1

В строке номер row должно быть row символов — условие внутреннего цикла зависит от внешнего.

Подсказка 2

for (let col = 1; col <= row; col++) { line += symbol; }

ЗАДАЧА 7.4

Найдите баг: растущие строки

средняя

Код должен нарисовать три одинаковые строки ***, а рисует растущую лесенку. Запустите, найдите причину и исправьте — не меняя количество циклов.

Можно редактировать · Ctrl + Enter
let line = "";
for (let row = 1; row <= 3; row++) {
  for (let col = 1; col <= 3; col++) {
    line += "*";
  }
  console.log(line);
}
Ожидаемый результат после исправления
***
***
***
Подсказка 1

Переменная line объявлена один раз и никогда не очищается — все звёздочки копятся в ней дальше.

Подсказка 2

Перенесите let line = ""; внутрь внешнего цикла, перед внутренним.

ЗАДАЧА 7.5

Шахматная доска

сложная

Нарисуйте доску 4 × 4: клетки чередуются — # и .. Первая клетка — #. Подсказка к идее: клетка «тёмная», если сумма номеров строки и столбца (считаем с нуля) чётная.

Можно редактировать · Ctrl + Enter
// строки и столбцы с нуля: 0..3
Ожидаемый результат
#.#.
.#.#
#.#.
.#.#
Подсказка 1

Циклы for (let row = 0; row < 4; row++) и for (let col = 0; col < 4; col++).

Подсказка 2

Внутри: if ((row + col) % 2 === 0) { line += "#"; } else { line += "."; }. Не забудьте про line для каждой строки.

08 Бесконечный цикл: как не зависнуть

Цикл остановится, только если его условие когда-нибудь станет false. Если условие всегда истинно, цикл не закончится никогда. Это бесконечный цикл, и это самая известная ошибка начинающих (и не только) программистов. Страница с таким циклом «зависает»: кнопки не нажимаются, вкладка не отвечает.

Аналогия из жизни

Таксист включил счётчик и забыл его выключить. Пассажир давно вышел, а цифры продолжают расти — и так, пока кто-то не остановит машину. Цикл без изменяемого счётчика — такое же «забытое» такси.

Как это выглядит на нашей странице

Раннер на этой странице защищён: если код «молчит» дольше нескольких секунд, он принудительно останавливается и пишет красное сообщение. Нажмите ▶ Запустить и подождите примерно три секунды:

Бесконечный цикл: остановится сам через ~3 секунды · Ctrl + Enter
let i = 1;
while (i <= 5) {
  // забыли написать i++ — условие всегда true
}
console.log("Эта строка никогда не выполнится");

Вы увидите сообщение ⏱ Код выполняется слишком долго (возможен бесконечный цикл). Это страховка только нашей страницы. В обычной программе или на реальном сайте такой подстраховки нет, и всё просто зависнет.

Откуда берутся бесконечные циклы

ПричинаПримерКак исправить
Забыли менять счётчикwhile (i <= 5) { … } без i++Добавить i++ в тело
Меняем в неправильную сторонуfor (let i = 10; i > 0; i++)i--
Условие никогда не ложноfor (let i = 1; i !== 10; i += 2) — перескочит через 10Использовать < вместо !==
continue до изменения счётчикасм. раздел 04Менять счётчик до continue
Осознанный while (true) без выходазабыли breakВсегда продумывать break

Три вопроса перед запуском цикла

  1. Что меняется на каждом круге? Должна меняться переменная из условия.
  2. В какую сторону она меняется? К границе условия, а не от неё.
  3. Может ли условие стать false? Подставьте 2–3 значения и проверьте руками.

Предохранитель: цикл, который не может зависнуть

Когда пишете цикл с нетривиальным условием, добавьте счётчик кругов и ограничьте его. Если что-то пойдёт не так — цикл сам выйдет, и вы увидите это в консоли, а не получите зависшую страницу:

Предохранитель · Ctrl + Enter
let money = 18;
let rounds = 0;

while (money > 0) {
  rounds++;
  if (rounds > 100) {          // предохранитель
    console.log("Аварийная остановка: слишком много кругов");
    break;
  }
  money -= 6;                  // уменьшаем деньги на 6
}
console.log(`Кругов: ${rounds}, денег: ${money}`);
Что делать, если зависло

В браузере: закройте вкладку (иногда браузер сам предлагает остановить страницу). В терминале при запуске node: нажмите Ctrl + C. В обоих случаях — найдите цикл и ответьте на три вопроса выше.

Читать подробнее: MDN — Циклы и итерация · learn.javascript.ru — Циклы

Практика: закрепляем

ЗАДАЧА 8.1

Остановите зависший цикл

лёгкая

Цикл должен вывести три урока, но в нём забыли изменить счётчик. Чтобы страница не зависла, в код добавлен предохранитель — он срабатывает через 6 кругов и выводит «Аварийная остановка». Найдите, чего не хватает, и исправьте. Предохранитель не удаляйте — после исправления он просто не сработает.

Можно редактировать · Ctrl + Enter
let lesson = 1;
let safety = 0;

while (lesson <= 3) {
  console.log(`Урок ${lesson}`);

  safety++;
  if (safety > 5) {
    console.log("Аварийная остановка");
    break;
  }
}
Ожидаемый результат после исправления
Урок 1
Урок 2
Урок 3
Подсказка 1

Что меняется в условии lesson <= 3 на каждом круге? Сейчас — ничего.

Подсказка 2

Добавьте в тело цикла строку lesson++;.

09 ИИ-блок: объяснить чужой код построчно

В работе вы почти никогда не пишете код с нуля: чаще читаете то, что написал коллега, нашли в интернете или выдал ИИ. Умение разобрать чужой цикл — один из главных навыков. ИИ здесь отличный помощник, если просить правильно: не «реши», а «объясни, как новичку».

Правила курса про ИИ — напоминаем

1) Сначала 15 минут пробуете разобраться сами: выпишите, чему равны переменные на первых трёх кругах. 2) Не вставляете код, который не можете объяснить строчка за строчкой. 3) В промпте всегда: контекст → задача → ограничения → формат ответа → проверка.

Возьмём чужой код

Допустим, коллега прислал такую программу. Что она делает?

Чужой код · Ctrl + Enter
let total = 0;
for (let n = 1; n <= 10; n++) {
  if (n % 2 === 0) continue;
  total += n;
}
console.log(total);

Слабый и сильный запрос

объясни код
Контекст: я новичок в JavaScript. Знаю переменные, типы, условия if и циклы for/while. Функций и массивов пока не знаю. Задача: объясни, как новичку, что делает этот код: [код] Ограничения: не переписывай код. Если встретится незнакомое слово, объясни его простыми словами в одну строку. Формат ответа: таблица «строка кода → что делает». Потом — значения переменных после каждого из первых трёх кругов цикла. В конце одно предложение: что делает вся программа. Проверка: назови одно изменение, которое поменяет результат, и скажи, что получится.

Как проверить объяснение ИИ

ИИ может объяснять уверенно — и ошибаться. Поэтому ответ всегда проверяется по трём шагам:

  1. Запустите код и запишите настоящий вывод в консоли.
  2. Сравните с тем, что «сказал» ИИ. Не совпало — ИИ ошибся, верьте консоли.
  3. Добавьте трассировку: console.log внутри цикла, который печатает счётчик и накопитель на каждом круге. Так вы видите весь путь, а не только результат.

Ещё два шаблона для тренировки

Из библиотеки промптов курса: попросить объяснить построчно без переписывания и попросить задачи без готовых решений.

Вот код: [код]. Объясни построчно, что происходит и почему результат такой. Не переписывай код — только объясни.
Дай 5 задач на циклы уровня новичка, от простой к сложной, без решений. Используй только for, while, if и строки — без функций и массивов.

Проверка ответа: убедитесь, что задачи по теме и в ответе нет готового кода решения. Решения вы ищете сами.

Типичные ошибки ИИ при объяснении циклов

Что может быть в ответе ИИВ чём проблемаКак проверить
Объясняет, «для чего» программа, но не показывает значения переменныхВы не видите, как меняется накопительПопросить «покажи значения после каждого круга» или добавить console.log
Путает < и <=Ошибка на единицу: последний круг теряется или появляется лишнийПроверить первое и последнее значение счётчика руками
Называет вывод «по памяти», не выполняя кодИИ не запускает код — он предполагает результатВсегда запускайте код и сверяйте
Переписывает цикл на незнакомые методы (reduce, filter)Вы не сможете объяснить такой код на защитеДобавить «только for/while, без методов массивов»
Не замечает риск бесконечного циклаКод может зависнуть на других данныхЗадать три вопроса из раздела 08 про этот цикл

Практика: закрепляем

ЗАДАЧА 9.1

Проверьте слова ИИ трассировкой

средняя

Представьте, что ИИ объяснил чужой код выше так: «Программа складывает числа от 1 до 10 и выводит 55». Проверим. Добавьте в цикл трассировку: после строки total += n выводите n=…, total=… на каждом круге. Что в итоге на самом деле считает программа?

Можно редактировать · Ctrl + Enter
let total = 0;
for (let n = 1; n <= 10; n++) {
  if (n % 2 === 0) continue;
  total += n;
  // добавьте трассировку здесь
}
console.log(total);
Ожидаемый результат
n=1, total=1
n=3, total=4
n=5, total=9
n=7, total=16
n=9, total=25
25
Подсказка 1

Трассировка — обычный console.log внутри цикла, но после continue и после total += n.

Подсказка 2

Строка: console.log(`n=${n}, total=${total}`);. Ответ на вопрос: программа складывает только нечётные числа, а чётные пропускает через continue; ИИ ошибся.

10 Практика на уроке: четыре классические задачи

FizzBuzz, таблица умножения, простые числа и пирамида — программы, которые просят на собеседованиях и которыми учатся все начинающие программисты в мире. Идём по порядку, у каждой — разбор и затем задача с проверкой. Набирайте код сами, не копируйте.

1. FizzBuzz

Условие: выведите числа от 1 до 15. Но если число делится на 3 — вместо него слово Fizz, если на 5 — Buzz, если сразу и на 3, и на 5 — FizzBuzz.

План: цикл по числам, внутри цепочка if / else if / else. Самая частая ловушка — порядок проверок. Посмотрите, что получится, если проверить «на 3» первым:

Неправильный порядок: для 15 выводится Fizz, а не FizzBuzz · Ctrl + Enter
for (let i = 1; i <= 15; i++) {
  if (i % 3 === 0) {
    console.log("Fizz");
  } else if (i % 5 === 0) {
    console.log("Buzz");
  } else if (i % 15 === 0) {
    console.log("FizzBuzz");   // до этой ветки дело не дойдёт
  } else {
    console.log(i);
  }
}

Общее правило цепочки if / else if: самое узкое условие — первым. Число, делящееся и на 3, и на 5, — самый редкий случай.

ЗАДАЧА 10.1

FizzBuzz

средняя

Напишите правильный FizzBuzz для чисел от 1 до 15.

Можно редактировать · Ctrl + Enter
for (let i = 1; i <= 15; i++) {
  // цепочка if / else if / else
}
Ожидаемый результат
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
Подсказка 1

Первой проверьте делимость на 3 и на 5 одновременно: i % 3 === 0 && i % 5 === 0 (или одно условие i % 15 === 0).

Подсказка 2

Дальше else if для 3, потом else if для 5, и в конце else — просто вывести i.

2. Таблица умножения

Условие: таблица умножения 9 × 9: в каждой строке — произведения номера строки на числа от 1 до 9. Это уже знакомый нам двойной цикл со строкой-накопителем:

Заготовка: таблица 3 × 3 · Ctrl + Enter
for (let row = 1; row <= 3; row++) {
  let line = "";
  for (let col = 1; col <= 3; col++) {
    line += row * col + " ";
  }
  console.log(line);
}
ЗАДАЧА 10.2

Таблица умножения 9 × 9

средняя

Расширьте заготовку до 9 × 9. Числа в строке разделяйте пробелом.

Можно редактировать · Ctrl + Enter
for (let row = 1; row <= 3; row++) {
  let line = "";
  for (let col = 1; col <= 3; col++) {
    line += row * col + " ";
  }
  console.log(line);
}
Ожидаемый результат
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
Подсказка 1

Измените обе границы: row <= 9 и col <= 9.

Подсказка 2

Лишний пробел в конце строки проверку не испортит — пробелы по краям игнорируются.

3. Простые числа

Условие: найти все простые числа до 30. Простое число делится только на 1 и на само себя (2, 3, 5, 7, 11…). Единица простой не считается.

План: сначала научимся проверять одно число. Пробуем делители d от 2 до n - 1. Нашёлся делитель — число составное, дальше проверять незачем (break). Результат держим в «флажке» — переменной true / false:

Проверяем одно число · Ctrl + Enter
const n = 29;
let isPrime = true;                 // пока считаем простым

for (let d = 2; d < n; d++) {
  if (n % d === 0) {                // нашли делитель
    isPrime = false;
    break;
  }
}

console.log(`${n} — ${isPrime ? "простое" : "составное"}`);

Попробуйте n = 21 и n = 2. Теперь оберните проверку во внешний цикл по n от 2 до 30 и собирайте простые числа в строку-накопитель.

ЗАДАЧА 10.3

Простые числа до 30

сложная

Выведите все простые числа от 2 до 30 в одной строке через пробел, после текста «Простые числа до 30:».

Можно редактировать · Ctrl + Enter
let primes = "";
// внешний цикл по n, внутренний по делителям d

console.log("Простые числа до 30: " + primes);
Ожидаемый результат
Простые числа до 30: 2 3 5 7 11 13 17 19 23 29
Подсказка 1

Для каждого n заново ставьте let isPrime = true — внутри внешнего цикла, перед внутренним. Это тот же приём «обнулять накопитель для каждой строки».

Подсказка 2

После внутреннего цикла: if (isPrime) { primes += n + " "; }. Для n = 2 внутренний цикл не выполнится ни разу (d = 2 не меньше 2), и двойка остаётся простой — как и нужно.

4. Пирамида из символов

Условие: нарисовать пирамиду высотой 5. В строке номер row нужно (height − row) пробелов слева и (2·row − 1) символов. Для первой строки это 4 пробела и 1 звезда, для последней — 0 пробелов и 9 звёзд.

  1. Внешний цикл по строкам: row от 1 до height.
  2. Первый внутренний цикл добавляет в строку пробелы.
  3. Второй внутренний цикл добавляет символы.
  4. Готовую строку выводим после обоих внутренних циклов.
ЗАДАЧА 10.4

Пирамида

сложная

Нарисуйте пирамиду высотой 5 из символа symbol. Затем поменяйте symbol на # и height на 3 — убедитесь, что код работает для любых значений.

Можно редактировать · Ctrl + Enter
const symbol = "*";
const height = 5;

for (let row = 1; row <= height; row++) {
  let line = "";
  // пробелы
  // символы
  console.log(line);
}
Ожидаемый результат
    *
   ***
  *****
 *******
*********
Подсказка 1

Пробелы: for (let s = 1; s <= height - row; s++) { line += " "; }.

Подсказка 2

Символы: for (let k = 1; k <= 2 * row - 1; k++) { line += symbol; }. Пробелы идут первым циклом, символы — вторым.

Итог практики

В четырёх задачах встретились все инструменты урока: for и условие, вложенные циклы, флажок true/false с break, накопитель-строка. Эти же приёмы лежат в основе почти любой задачи на циклы в домашней работе.

11 Домашнее задание: loops.js

Результат домашней работы — один файл loops.js с решениями восьми задач и отдельный файл explain.md с разбором чужого решения вместе с ИИ. Задачи решаются только тем, что мы прошли: переменные, условия, for, while, for..of, break, continue. Функций и массивов нет.

8 задач

Каждую задачу оформляйте отдельным блоком: комментарий с номером и названием, затем код. Проверяйте решение запуском — выводом должно получиться то, что описано.

  1. Таблица на 7. Выведите таблицу умножения на 7 от 1 до 10: 7 × 1 = 7, … , 7 × 10 = 70.
  2. Чётные числа. Найдите сумму всех чётных чисел от 1 до 100. Ответ — 2550.
  3. Обратный отсчёт. Выведите числа от 10 до 1, но число 5 пропустите (continue), а после цикла выведите «Пуск!».
  4. Факториалы. Для каждого n от 1 до 10 выведите строку n! = … (вложенный цикл не нужен: накопитель можно обновлять прямо во внешнем цикле). Последняя строка: 10! = 3628800.
  5. Гласные. Посчитайте гласные в строке "ассалому алейкум" (а, е, о, у). Ответ — 7. Проверка «буква гласная» — через цепочку ||.
  6. Фибоначчи. Выведите первые 12 чисел Фибоначчи (каждое следующее — сумма двух предыдущих): 1 1 2 3 5 8 13 21 34 55 89 144. Нужны две переменные «предыдущее» и «текущее».
  7. Сумма цифр. Найдите сумму цифр числа 98765. Подсказка: n % 10 — последняя цифра, Math.floor(n / 10) — число без неё. Ответ — 35.
  8. Ёлочка-ромб. Нарисуйте ромб высотой 7 из символа *: верх — пирамида из практики (4 строки), низ — перевёрнутая (3 строки). Ширина самой широкой строки — 7.

Разбор чужого решения с ИИ

Вот решение, которое «нашли в интернете». Оно считает сумму всех чисел от 1 до 100, кратных 3 или 5. Запустите его:

Чужое решение · Ctrl + Enter
let sum = 0;
for (let i = 1; i <= 100; i++) {
  if (i % 3 !== 0 && i % 5 !== 0) continue;
  sum += i;
}
console.log(sum);
  1. Потратьте 15 минут: выпишите в тетрадь, что делает каждая строка и почему условие записано через !== и &&.
  2. Дайте код ИИ по сильному шаблону из раздела 09 (формула «объясни как новичку»). Сохраните свой промпт.
  3. Сравните ответ с настоящим выводом (2418) и со своими записями. Добавьте трассировку console.log и покажите хотя бы три круга.
  4. Перепишите условие так, чтобы оно читалось проще, без continue: if (i % 3 === 0 || i % 5 === 0) { sum += i; }. Убедитесь, что результат тот же.
  5. В explain.md напишите: (а) свой промпт; (б) что ИИ объяснил верно; (в) что ИИ упустил или написал неточно; (г) что вы бы не взяли из его ответа и почему.

Что сдать

  • Файл loops.js с восемью задачами. Каждая выводит результат в консоль.
  • Файл explain.md с разбором (пункты а–г). Минимум 8 содержательных строк, без копирования ответа ИИ целиком.
  • Ссылка на GitHub-репозиторий или архив в Telegram-группу.

Как оценим (0–10)

КритерийБаллыЧто смотрим
Задачи 1–44По 1 баллу за задачу: код работает и даёт ожидаемый вывод, нет лишнего
Задачи 5–84По 1 баллу за задачу; за ромб — полный балл, если ширина и симметрия верные
Разбор с ИИ2Промпт по шаблону, честный анализ ответа, видно, что вы поняли код

Бонус (без баллов): шахматная доска 8 × 8, числа-палиндромы от 100 до 200, треугольник Паскаля.

Напоминание

На проверке преподаватель может попросить объяснить любую строку вашего loops.js. Если вы не можете объяснить, почему в задаче про простые числа флажок объявлен внутри внешнего цикла, — решение нужно разобрать заново.

✓ Шпаргалка урока

  • Цикл повторяет блок кода. Один проход — итерация. Условие проверяется перед каждым кругом.
  • while: while (условие) { … } — когда число кругов неизвестно. Счётчик нужно менять в теле.
  • for: for (старт; условие; шаг) { … } — когда число кругов известно. Порядок: старт (один раз) → условие → тело → шаг → условие…
  • do..while: do { … } while (условие); — тело выполнится минимум один раз, условие проверяется после.
  • break выходит из цикла совсем, continue пропускает остаток круга. Внутри вложенных циклов break выходит только из внутреннего.
  • for..of по строке: for (const ch of "текст"). Нужен номер буквы — for с text[i] и text.length. Индексы с нуля, последний — length - 1. Строку «по месту» не изменить — собираем новую.
  • Накопители: сумма — старт 0, произведение — старт 1, счётчик — count++ по условию, максимум — if (x > best), строка — line += …. Объявляем до цикла.
  • Вложенные циклы: тело внутреннего выполняется «круги внешнего × круги внутреннего» раз. Строку для рисунка собираем внутренним циклом и выводим после него. Накопитель строки — внутри внешнего цикла.
  • Остаток от деления %: x % 2 === 0 — чётное, x % 3 === 0 — кратно 3.
  • Бесконечный цикл: условие всегда true. Причины — забыли менять счётчик, меняем не в ту сторону, continue до шага, нет break у while (true). Три вопроса перед запуском: что меняется, в какую сторону, может ли условие стать false. Помогает предохранитель — счётчик кругов с break.
  • С ИИ: чужой код — «объясни как новичку, построчно, покажи значения на первых кругах, не переписывай». Ответ всегда проверяйте запуском и трассировкой console.log.