Цикл

Программирование построено на повторном выполнении кода. Разбираемся с концепцией, а не с синтаксисом.

Время чтения: меньше 5 мин

Кратко

Скопировано

Цикл — это повторяющаяся последовательность действий.

Цикл состоит из условия и тела цикла.

Перед запуском цикла проверяется условие. Если условие истинное, то выполняется блок кода, который называется телом цикла. Затем этот шаг повторяется. Так будет продолжаться, пока условие не станет ложным.

Каждое выполнение тела цикла называется итерацией.

JavaScript предоставляет несколько способов создания цикла. Самые распространённые из них — while и for (инициализация; условие; завершающая операция) {}

Как понять

Скопировано

Зачем нужны циклы, читайте в статье Порядок выполнения

Иллюстрация дракон держит в зубах свой хвост

В программировании есть много задач, когда нужно выполнять заранее неизвестное количество однотипных шагов:

  • напечатать все сообщения из списка;
  • обозначить на карте присланные пользователем координаты;
  • уточнять значения при вычислении функций (например, считать квадратный корень).

До выполнения программы невозможно знать, сколько будет сообщений или сколько раз нужно уточнить значение для точного расчёта квадратного корня. Такие задачи решают циклы.

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

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

Опишем работу цикла словами:

  1. проверь, выполняется ли условие.
  2. если условие выполняется, выполни тело цикла. Затем вернись в пункт 1.
  3. если условие не выполняется, цикл завершён.

Цикл удобно представлять схемой:

схема работы цикла

Условие

Скопировано

Нужно хорошо понимать, как работает условие, чтобы уверенно работать с циклами. Условие — это выражение, которое JavaScript вычислит в значение.

В простом случае, условие вычисляется в логический тип: true, либо false. Такие выражения получаются при использовании операторов сравнения ==, ===, >, <, >=, <=, !==, !=.

Например:

        
          
          let count = 10while (count > 0) {  console.log(count)  count--}
          let count = 10
while (count > 0) {
  console.log(count)
  count--
}

        
        
          
        
      

Код напечатает числа от 10 до 1 на экран.

Выражения в условии можно комбинировать с помощью логических операторов.

В более сложном случае условие будет вычисляться в какой-либо другой тип: число, строку, массив, объект и т.д. В этом случае JavaScript будет приводить получившееся значение к логическому типу.

        
          
          let count = 10while (count) {  console.log(count)  count--}
          let count = 10

while (count) {
  console.log(count)
  count--
}

        
        
          
        
      

Чтобы понять, какой когда цикл остановится, нужно запомнить правила приведения различных типов к логическому. Главное правило:

Все, что не приводится к false, будет true

Осталось запомнить 8 значений, которые приводятся к false:

  • false
  • 0
  • -0
  • ''
  • null
  • undefined
  • NaN
  • 0n(тип BigInt)

Зная это правило, мы поймём, что цикл перестанет работать после 10 итераций и напечатает числа от 10 до 1.

Тело цикла

Скопировано

Тело цикла — это набор инструкций, заключённый в фигурные скобки. Одно выполнение тела называют итерацией цикла.

Ограничений на операции в теле цикла нет. Тело может содержать объявление переменных, вызовы функций, другие управляющие конструкции и циклы.

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

Скопировано

Если условие цикла написано так, что оно никогда не станет ложным, цикл будет выполняться бесконечно.

схема бесконечного цикла

Такой цикл занимает все выделенные ресурсы компьютера. В итоге вкладка браузера или целая программа зависает.

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

Открыть демо в новой вкладке

К бесконечному циклу могут привести две ошибки:

  • неверное условие;
  • условие написано верно, но в теле цикла никак не изменяются переменные, которые используются в условии.

На практике

Скопировано

Николай Лопин советует

Скопировано

🛠 Составляйте условие так, чтобы оно менялось после каждой итерации цикла. Каждая итерация цикла должна приближать момент остановки цикла.

🛠 Внутри цикла можно использовать оператор break, он прерывает цикл:

        
          
          let count = 5while (count > 0) {  if (count === 2) {    break // цикл прервётся здесь, оператор break убивает цикл  }  console.log(count)  count--}// 5, 4, 3
          let count = 5
while (count > 0) {
  if (count === 2) {
    break // цикл прервётся здесь, оператор break убивает цикл
  }
  console.log(count)
  count--
}

// 5, 4, 3

        
        
          
        
      

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

        
          
          let count = 5while (count > 2) {  console.log(count)  count--}// напечатает 5, 4, 3
          let count = 5
while (count > 2) {
  console.log(count)
  count--
}

// напечатает 5, 4, 3

        
        
          
        
      

🛠 Внутри цикла можно использовать оператор continue, он прерывает текущую итерацию и возвращается к проверке условия:

        
          
          let count = 5while (count > 0) {  count--  if (count === 2) {    continue // когда count будет равен 2, итерация прервется здесь и не дойдет до печати  }  console.log(count)}// напечатает 4, 3, 1, 0
          let count = 5
while (count > 0) {
  count--
  if (count === 2) {
    continue // когда count будет равен 2, итерация прервется здесь и не дойдет до печати
  }
  console.log(count)
}

// напечатает 4, 3, 1, 0

        
        
          
        
      

Оператор стараются не использовать, потому что он усложняет чтение кода — появляется ещё одно место, где итерация может завершиться. Почти всегда цикл с continue можно переписать на цикл без него, добавив ветвление if:

        
          
          let count = 5while (count > 0) {  count--  if (count !== 2) {    console.log(count)  }}// напечатает 4, 3, 1, 0
          let count = 5
while (count > 0) {
  count--
  if (count !== 2) {
    console.log(count)
  }
}

// напечатает 4, 3, 1, 0