Види циклів у JS
У JavaScript цикли діляться на оператори з умовою (for, while, do...while) та оператори перебору (for...in, for...of), до яких додаються методи масивів на зразок forEach. Різниця між ними в тому, що саме керує повтореннями: лічильник, умова, ключі об’єкта чи ітератор колекції.
Теорія
TL;DR
forце класичний цикл, коли кількість ітерацій відома заздалегідь.whileце цикл з передумовою: тіло може не виконатися жодного разу.do...whileце цикл з післяумовою: тіло гарантовано виконається хоча б один раз.for...inперебирає перелічувані ключі об’єкта, включно з успадкованими, і не гарантує порядок.for...ofперебирає значення ітерованих об’єктів: масивів, рядків,Set,Map,arguments.forEachце не оператор, а метод масиву; у ньому не працюютьbreakіcontinue.
Швидкий приклад
const numbers = [10, 20, 30];
for (let i = 0; i < numbers.length; i++) console.log(numbers[i]); // за індексом
for (const value of numbers) console.log(value); // за значенням
numbers.forEach((value, index) => console.log(index, value)); // метод масивуЦикли з лічильником та умовою
1. for, класичний цикл
Використовується, коли заздалегідь відома кількість ітерацій.
for (let i = 0; i < 5; i++) {
console.log(i);
}Результат:
0
1
2
3
4Структура:
for (ініціалізація; умова; крок) {
// тіло циклу
}ініціалізаціявиконується один раз на початку;умоваперевіряється перед кожною ітерацією;кроквиконується після кожної ітерації.
2. while, цикл з передумовою
Виконується, доки умова істинна (true).
let i = 0;
while (i < 5) {
console.log(i);
i++;
}Використовується, коли кількість ітерацій невідома заздалегідь, наприклад доки черга не порожня або доки сервер не віддав останню сторінку.
3. do...while, цикл з післяумовою
Гарантовано виконається хоча б один раз, бо умова перевіряється вже після тіла.
let i = 5;
do {
console.log(i);
i++;
} while (i < 5);Результат:
5Спочатку виконується тіло циклу, і лише потім перевіряється умова.
Оператори перебору
4. for...in, перебір ключів об’єкта
Використовується для проходу по властивостях об’єкта.
const user = { name: 'Tim', age: 25, city: 'Kyiv' };
for (const key in user) {
console.log(key, ':', user[key]);
}Результат:
name : Tim
age : 25
city : KyivОсобливості:
- перебирає всі перелічувані властивості, включно з успадкованими через прототип;
- не гарантує порядку (цілочисельні ключі йдуть першими за зростанням);
- краще не використовувати для масивів: ключі приходять рядками (
'0','1'), а разом із ними можуть прийти й сторонні властивості.
5. for...of, перебір ітерованих об’єктів
Ідеальний для масивів, рядків, Set, Map та інших ітерованих структур.
const numbers = [10, 20, 30];
for (const num of numbers) {
console.log(num);
}Результат:
10
20
30Працює і з рядком:
for (const char of 'JS') {
console.log(char);
}На відміну від for...in, він перебирає значення, а не ключі. Якщо потрібен і індекс, беруть for (const [i, value] of arr.entries()).
6. Метод forEach()
Це не оператор, а метод масиву, але виконує ту саму задачу: перебір.
const arr = ['a', 'b', 'c'];
arr.forEach((value, index) => {
console.log(index, value);
});Результат:
0 a
1 b
2 cОсобливості:
- не можна використати
breakабоcontinue, аreturnусередині колбека лише завершує поточну ітерацію; - зручний для перебору без дострокового виходу;
- пропускає «дірки» у розріджених масивах;
- поруч із ним стоять
map,filter,reduce,some,every, які повертають результат, тоді якforEachзавжди повертаєundefined.
Порівняльна таблиця
| Цикл | Що перебирає | Коли брати | break / continue |
|---|---|---|---|
for | індекси, лічильник | кількість ітерацій відома | так |
while | нічого, лише умова | кількість ітерацій невідома | так |
do...while | нічого, лише умова | треба хоча б один прохід | так |
for...in | перелічувані ключі об’єкта | обхід властивостей об’єкта | так |
for...of | значення ітерованого об’єкта | масиви, рядки, Set, Map | так |
forEach | елементи масиву | простий перебір без виходу | ні |
Типові помилки
- Використовувати
for...inдля масивів: отримаєте рядкові ключі та ризик зачепити успадковані властивості. Для масивів берітьfor...ofабо звичайнийfor. - Чекати, що
breakзупинитьforEach. Він не зупиняє; якщо потрібен достроковий вихід, візьмітьfor...of,someабоfind. - Забути змінити лічильник у
whileі отримати нескінченний цикл. - Плутати
do...whileіwhile: перший завжди виконує тіло хоча б раз, навіть коли умова хибна від початку. - Оголошувати лічильник через
varу циклі з асинхронним колбеком: усі колбеки побачать одне й те саме кінцеве значення, боvarне має блокової області видимості. Рятуєlet. - Викликати
awaitусерединіforEach: метод не чекає на проміси, тому потрібенfor...ofзawaitабоPromise.all.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.