Циклы и производительность

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

Избегать тяжёлых операций внутри тела цикла

Любая операция, которая не зависит от итерации, не должна выполняться на каждой итерации.

❌ Плохо — вычисление длины массива на каждой итерации

const items = getLargeItemList(); // 10 000 элементов

for (let i = 0; i < items.length; i++) {
  // items.length вызывается 10 000 раз — даже если массив не меняется
  processItem(items[i]);
}

items.length — это свойство. В JavaScript оно вычисляется каждый раз, даже если массив статичен. Это лишняя нагрузка.

✅ Хорошо — вычислить один раз до цикла

const items = getLargeItemList();
const length = items.length; // вычисляем один раз

for (let i = 0; i < length; i++) {
  processItem(items[i]);
}

Теперь length — это просто число, и его не нужно пересчитывать.

❌ Плохо — вызов функции или сложных вычислений внутри цикла

for (let item of items) {
  if (item.name.toLowerCase().includes(searchTerm.toLowerCase())) {
    //toLowerCase() вызывается дважды на каждой итерации
    result.push(item);
  }
}

Каждый вызов toLowerCase() — это новая строка, которая создаётся и сравнивается. Это лишние выделения памяти и вычисления.

✅ Хорошо — вынести константные операции за цикл

const lowerSearchTerm = searchTerm.toLowerCase();

for (let item of items) {
  if (item.name.toLowerCase().includes(lowerSearchTerm)) {
    result.push(item);
  }
}

Дополнительные оптимизации

  • Избегайте сложных вычислений внутри цикла: математика, регулярные выражения, вызовы JSON.parse, querySelector.
  • Выносите константы за пределы цикла: например, Math.PI, config.threshold, RegExp-шаблоны.
  • Не модифицируйте массив, который перебираете — это может вызвать неожиданное поведение, особенно при использовании for...of.
  • Используйте for...of вместо for с индексами, если вам не нужны индексы — меньше кода, меньше рисков.

Правило

Всё, что не меняется на каждой итерации — выносите за цикл.
Всё, что влияет на производительность (вычисления, вызовы функций) — минимизируйте внутри цикла.
Оптимизация циклов напрямую влияет на скорость выполнения скрипта и отзывчивость приложения.