break и continue: управление циклом

ветвления≈ 7 минут

Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.

Цикл не обязан честно доходить до конца. break обрывает его целиком, continue отправляет на следующий круг — два коротких слова, которые убирают из кода половину вложенных if.

Разделы темы:·

break — это «хватит». Он немедленно прекращает цикл, внутри которого стоит, и управление уходит на первую строку после цикла. Всё, что осталось в теле итерации ниже break, не выполняется — ни одной строки.

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

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Второе по частоте применение — цикл, у которого условие выхода живёт не в заголовке, а посередине тела. Тогда заголовок пишут заведомо бесконечным (while (true)), а выход отдают break. Это законный приём, а не признак плохого кода — главное, чтобы выход существовал.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

continue не выходит из цикла, а обрывает только текущую итерацию: остаток тела пропускается, и работа продолжается со следующего круга. Для for «следующий круг» означает сначала шаг (i++), потом проверку условия — счётчик не застревает.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

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

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

У for шаг счётчика записан в заголовке, и continue его не пропускает. У while шаг делаете вы сами — и если continue стоит раньше строки с увеличением счётчика, до неё уже никогда не дойдёт. Правило простое: сначала двигаем счётчик, потом решаем, пропускать ли итерацию.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

break знает только про свой цикл. Из внутреннего он выкинет вас во внешний, а не наружу — и внешний спокойно пойдёт на следующую итерацию. Чтобы указать адрес точнее, циклу дают метку: имя с двоеточием перед словом for или while, а затем пишут break имя.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

continue с меткой работает так же адресно: он завершает текущую итерацию помеченного цикла и переводит именно его на следующий шаг. Внутренний цикл при этом просто заканчивается досрочно.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Меткой можно пометить не только цикл, но и обычный блок кода, и выйти из него через break. Но прыгнуть меткой вперёд или назад, как в старом goto, нельзя: метка не место назначения, а имя конструкции, которую вы досрочно закрываете. Поэтому запутать поток управления ею куда сложнее, чем кажется.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Ранний выход — это приём, а не просто оператор: к цепочке if мы прикладывали его в статье «Условия: if, else и тернарный оператор», а внутри цикла ту же работу делает continue. Вместо того чтобы вкладывать условия одно в другое и уводить полезный код на четвёртый уровень отступа, сначала отсеивают всё лишнее короткими continue, а главное действие оставляют на ровном месте — его видно сразу.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Внутри функции ту же работу делает return: он и цикл прерывает, и функцию завершает, сразу отдавая результат. Поэтому связка «break плюс переменная-флаг плюс проверка после цикла» почти всегда разворачивается в одну строку.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Метки в живом коде — редкость. Потянулись за меткой — сначала прикиньте, не проще ли вынести внутренний цикл в функцию и выйти через return.

Сначала общая картина: чем именно отличаются четыре способа прервать ход цикла.

ОператорЧто прерываетЧто происходит дальше
breakвесь текущий циклкод сразу после цикла
continueтолько текущую итерациюшаг счётчика, затем проверка условия
break меткацикл с этой меткойкод после помеченного цикла
continue меткаитерацию помеченного цикласледующая итерация этого цикла
returnцикл и всю функциюкод после вызова функции

Первая ловушка — switch внутри цикла. Его собственный break закрывает switch, а не цикл: перебор пойдёт дальше как ни в чём не бывало. Чтобы выйти из цикла из ветки case, нужна метка.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Вторая ловушка — методы массивов. Массив умеет перебирать себя сам: forEach и map получают функцию — отдельный кусок кода — и вызывают её для каждого элемента. Цикл при этом спрятан внутри метода, а в вашем коде его нет, поэтому ни break, ни continue в теле такой функции не работают: прервать из неё чужой перебор нельзя. Подробно эти методы разбирает статья «Методы массивов: map, filter, reduce». Выхода из ловушки два: вернуться к for...of или взять метод, который сам умеет останавливаться, — например, find, с которым знакомит статья «Поиск и сортировка». И помните, что break и continue — инструкции, а не значения: в тернарный оператор или в правую часть присваивания их не поставить.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

  • break прекращает весь цикл: управление сразу переходит на строку после него, остаток итерации пропадает.
  • continue обрывает только текущую итерацию; у for шаг счётчика при этом всё равно выполняется, у while его нужно сделать до continue.
  • Метка перед циклом (имя с двоеточием) позволяет через break метка или continue метка адресоваться к внешнему циклу, а не к ближайшему.
  • Ранние continue и return вместо вложенных if держат код плоским: сначала отсеиваем лишнее, потом делаем главное.
  • break внутри switch закрывает switch, а не цикл; в forEach и map break и continue не работают — там нужны find, some, every или обычный for...of.

1/3Что окажется в переменной s? let s = 0; for (let i = 1; i <= 5; i++) { if (i === 3) break; s += i; } console.log(s);

2/3Сработал continue внутри цикла for (let i = 0; i < 3; i++). Что произойдёт дальше?

3/3Внутри for стоит switch, а в одной из его веток — обычный break. Что он прервёт?

Первое число, кратное 7

Найдите в массиве первое число, которое делится на 7 без остатка, и положите его в result. Если такого числа нет, result должен остаться null. Как только число найдено, перебор нужно прекратить.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Классический поиск: проверяем остаток от деления и выходим по первому совпадению.

jsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

Без break цикл дошёл бы до конца и записал в result число 35 — последнее подходящее вместо первого. Если вы решаете эту задачу внутри функции, замените break на return n: переменная-накопитель тогда не нужна вовсе.

Пара с суммой 10

Есть два массива. Найдите первую пару чисел (одно из a, другое из b), дающую в сумме 10, и запишите её в pair как массив из двух элементов. Перебор ведите слева направо: сначала все варианты для первого числа из a, потом для второго. Как только пара найдена, оба цикла должны остановиться.

js
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.

Простой break закрыл бы только внутренний цикл, и внешний продолжил бы работу впустую. Метка выключает оба разом.

jsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

Альтернатива без метки — вынести поиск в функцию и выйти через return [x, y]. В реальном коде так и делают чаще: имя функции заодно объясняет, что именно ищется.