Циклы в JavaScript

Циклы в JavaScript #

Цикл повторяет блок кода, пока выполняется условие или пока не исчерпан набор элементов. В современном JavaScript для массивов чаще выбирают for...of или методы массива; while и классический for остаются для счётчиков и условий с неизвестным числом шагов.


while и do…while #

while проверяет условие до тела цикла:

let battery = 100
let ticks = 0

while (battery > 20) {
  battery -= 15
  ticks += 1
}

ticks // 6
battery // 10

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

let pin
let attempts = 0

do {
  pin = String(1000 + attempts) // имитация ввода
  attempts += 1
} while (pin !== '1003' && attempts < 5)

attempts // 4

Осторожнее с условием, которое никогда не становится ложным — получите бесконечный цикл и «зависшую» вкладку.


Цикл for #

Классический счётчик — инициализация, условие, шаг:

const days = ['пн', 'вт', 'ср', 'чт', 'пт']
const schedule = []

for (let i = 0; i < days.length; i += 1) {
  schedule.push(`${i + 1}. ${days[i]}`)
}

schedule[0] // "1. пн"

Когда индекс не нужен, for...of короче и безопаснее (нет ошибки <= вместо <).


for…of и for…in #

for...of обходит значения итерируемого объекта (массив, строка, Map, Set):

const playlist = ['intro', 'groove', 'outro']
const labels = []

for (const track of playlist) {
  labels.push(track.toUpperCase())
}

labels // ["INTRO", "GROOVE", "OUTRO"]

for (const ch of 'JS') {
  // 'J', затем 'S'
}

for...in обходит ключи перечисляемых свойств объекта (включая унаследованные, если не фильтровать). Для массивов его обычно избегают: порядок и ключи-строки путают новичков.

const point = { x: 10, y: 24 }
const pairs = []

for (const key in point) {
  if (Object.hasOwn(point, key)) {
    pairs.push(`${key}=${point[key]}`)
  }
}

pairs // ["x=10", "y=24"]

break и continue #

  • break — выйти из цикла полностью.
  • continue — перейти к следующей итерации.
const rawScores = [91, null, 78, undefined, 85]
const cleaned = []

for (const score of rawScores) {
  if (score == null) continue
  if (score < 50) break
  cleaned.push(score)
}

cleaned // [91, 78, 85]

Для выхода из вложенных циклов используют метки — редко; чаще выносят логику в функцию с return.


Цикл или метод массива? #

const prices = [120, 450, 90]
const withTax = prices.map((p) => Math.round(p * 1.2))
const expensive = prices.filter((p) => p >= 100)
const total = prices.reduce((sum, p) => sum + p, 0)

Методы (map, filter, reduce, some, every) выражают намерение декларативно. Обычный цикл удобен, когда нужны break по сложному условию, несколько индексов или побочные эффекты на каждом шаге.

Подробнее методы массивов — в разделе «Данные».


Итог #

  • while / do...while — повторение по условию.
  • for — счётчик и индекс; for...of — значения коллекций.
  • for...in — ключи объекта; для массивов почти не используйте.
  • break / continue управляют потоком; для массивов часто хватает map / filter.

См. также #

Часто спрашивают

Чем let отличается от const?
Оба блочные. let допускает повторное присваивание, const — нет (содержимое объекта при этом можно менять). Подробнее
Зачем нужен use strict?
Строгий режим ловит случайные глобалы и делает this у «голых» вызовов равным undefined; в ES-модулях он включён по умолчанию. Подробнее
Почему лучше писать ===, а не ==?
=== не приводит типы молча; == запускает сложные правила приведения и чаще даёт неожиданный результат. Подробнее