Цикли в JavaScript

Цикли дають змогу залежно від певних умов виконувати деяку дію безліч разів. У JavaScript є такі види циклів:

  • for
  • for..in
  • for..of
  • while
  • do..while

Цикл for

Цикл for має таке формальне визначення:

for ([ініціалізація лічильника]; [умова]; [зміна лічильника]){
// дії
}

Наприклад, використовуємо цикл for для перебору чисел від 0 до 4:

for(let i = 0; i<5; i++){
console.log(i);
}

console.log("Кінець роботи");

Перша частина оголошення циклу - let i = 0 - створює та ініціалізує лічильник - змінну i. І перед виконанням циклу її значення дорівнюватиме 0. По суті це те ж саме, що й оголошення змінної.

Друга частина - умова, за якої буде виконуватися цикл: i<5. У цьому випадку цикл виконуватиметься, поки значення i не досягне 5.

Третя частина - i++ - збільшення лічильника на одиницю.

Тобто під час запуску змінна i дорівнює 0. Це значення відповідає умові i<5, тому буде виконуватися блок циклу, а саме рядок коду

console.log(i);

Після виконання блоку циклу виконується третя частина оголошення циклу - прирощення лічильника. Тобто змінна i стає рівною 1. Це значення також відповідає умові, тому блок циклу знову виконується. Таким чином, блок циклу спрацює 5 разів, поки значення i не стане рівним 5. Це значення НЕ відповідає умові, тому відбудеться вихід із циклу. І керування програмою перейде до інструкцій, які йдуть після блоку циклу. Консольний вивід програми:

0
1
2
3
4
Кінець роботи 

Кожне окреме повторення циклу називається ітерацією. Таким чином, у цьому випадку спрацюють 5 ітерацій.

При цьому необов'язково збільшувати лічильник на одиницю, можна робити з ним інші дії, наприклад, зменшувати на одиницю:

for(let i = 10; i > 5; i--){
console.log(i);
}

У цьому випадку на консоль виводиться числа від 10 до 6.

Або збільшимо лічильник на 2:

for(let i = 0; i < 10; i+=2){
console.log(i);
}

Тут виводяться на консоль усі парні числа від 0 до 8

При цьому можна опускати різні частини оголошення циклу:

let i = 0;

for(; i < 60;){
console.log(i);
i = i + 10;
}

У цьому випадку змінна i визначена поза циклом. У самому оголошенні циклу є тільки умова, інші дві частини відсутні. Зміна змінної відбувається в самому блоці циклу: вона збільшується на 10. У підсумку на консоль будуть виведені числа 0, 10, 20, 30, 40, 50.

Лічильник зручно використовувати як індекс елементів масиву і таким чином перебирати масив:

const people = ["Tom", "Sam", "Bob"];

for(let i=0; i < 3; i++){
console.log(people[i]);
}

Консольний вивід браузера:

Tom
Sam
Bob

Застосування декількох лічильників у циклі

За необхідності можна використовувати кілька лічильників:

for(let i = 1, j=1; i < 5, j < 4; i++, j++){
console.log(i + j);
}

// 1 ітерація: i=1, j=1; i + j = 2
// 2 ітерація: i=2, j=2; i + j = 4
// 3 ітерація: i=3, j=3; i + j = 6

Виконання дій в оголошенні циклу

Варто зазначити, що третя частина циклу, де зазвичай відбувається зміна лічильника, в реальності являє собою довільну дію, яка виконується після завершення циклу. Так, ми можемо написати таким чином:

for(let i = 0; i < 5; console.log(i++));
console.log("Кінець роботи");

Тут не визначено блоку циклу, а самі дії циклу визначено в третій частині заголовка циклу - console.log(i++)

Аналогічно в першій частині визначення циклу - ініціалізації ми можемо виконувати деякі дії, а не обов'язково тільки оголошення лічильника:

let i=0;

for(console.log("Init"); i < 5; i++){
console.log(i);
}

Тут визначення лічильника винесено поза циклом, а в ініціалізаційній частині циклу на консоль виводиться рядок. Виведення браузера:

Init
0
1
2
3

Вкладені цикли

Одні цикли можуть усередині себе містити інші:

for(let i=1; i <= 5; i++){
for(let j = 1; j <=5; j++){
console.log(i * j);
}
}

Тут один цикл включається в себе інший. У зовнішньому циклі визначається змінна i. Спочатку вона дорівнює 1 і це значення відповідає умові циклу(i <=5), тому буде виконуватися блок циклу, який містить внутрішній цикл.

У внутрішньому циклі визначається змінна-лічильник j, яка спочатку дорівнює 1, і потім внутрішній цикл виконує 5 ітерацій, поки змінна j не дорівнюватиме 5.

Після того, як блок зовнішнього циклу завершено, змінна i збільшується на 1 і стає рівною 2, що знову ж таки відповідає умові. І знову виконується блок зовнішнього циклу. У цьому блоці знову виконуються п'ять ітерацій внутрішнього циклу. І так далі. У підсумку внутрішній цикл буде виконуватися 25 разів.

Використовуючи вкладені цикли і кілька лічильників можна перебирати багатовимірні масиви:

const people = [[["Tom", 39], ["Sam", 28],["Bob", 42]];

for(let i=0; i < 3; i++){ // перебираємо двовимірний масив
for(let j=0; j < 2; j++){ // перебираємо вкладені масиви
console.log(people[i][j]);
}
console.log("================="); // для розділення елементів
}

Тут масив people представляє двовимірний масив із 3-х елементів, де кожен елемент представляє, своєю чергою, підмасив із 2-х елементів - умовно імені та віку користувача. У зовнішньому циклі визначаємо лічильник i для проходу по всіх підмасивах у двовимірному масиві people, а у внутрішньому циклі визначаємо лічильник j для проходу по всіх елементах кожного підмасиву. Консольний вивід:

Tom
39
=================
Sam
28
=================
Bob
42
=================

Цикл while

Цикл while виконується доти, доки деяка умова істинна. Його формальне визначення:

while(умова){
// дії
}

Знову ж таки виведемо за допомогою while числа від 1 до 5:

let i = 1;

while(i <=5){
console.log(i);
i++;
}

Цикл while тут виконуватиметься, поки значення i не стане рівним 6.

do..while

У циклі do спочатку виконується код циклу, а потім відбувається перевірка умови в інструкції while. І поки ця умова істинна, цикл повторюється. Наприклад:

let i = 1;

do{
console.log(i);
i++;
}while(i <= 5)

Тут код циклу спрацює 5 разів, поки i не стане рівним 5. При цьому цикл do гарантує хоча б одноразове виконання дій, навіть якщо умова в інструкції while не буде істинною.

Оператори continue і break

Іноді буває необхідно вийти з циклу до його завершення. У цьому випадку ми можемо скористатися оператором break:

for(let i=1; i <= 6; i++){
if(i===4) break;
console.log(i);
}

console.log("Кінець роботи");

Цей цикл збільшує змінну i з 1 до 6 включно, тобто згідно з умовою циклу блок циклу має виконуватися 6 разів, тобто провести 6 ітерацій. Однак оскільки в блоці циклу відбувається перевірка if(i===4) break;, то, коли значення змінної i досягне 4, то ця умова перерве виконання циклу за допомогою оператора break. І цикл завершить роботу.

1
2
3
Кінець роботи 

Якщо нам треба просто пропустити ітерацію, але не виходити з циклу, ми можемо застосовувати оператор continue. Наприклад, змінимо попередній приклад, тільки замість break використовуємо оператор continue:

for(let i=1; i <= 6; i++){
if(i===4) continue;
console.log(i);
}

console.log("Кінець роботи");

У цьому випадку, коли значення змінної i стане рівним 4, то вираз i===4 поверне true, тому виконуватиметься конструкція if(i===4) continue;. За допомогою оператора continue вона завершить поточну ітерацію, інструкції циклу, що йдуть далі, не будуть виконуватися, а відбудеться перехід до наступної ітерації:

1
2
3
5
6
Кінець роботи

for..in

Цикл for..in призначений головним чином для перебору об'єктів. Його формальне визначення:

for (властивість in об'єкт) {
// дії
}

Цей цикл перебирає всі властивості об'єкта. Наприклад:

const person = {ім'я: "Том", вік: 37};

for(prop in person){
console.log(prop);
}

Тут перебирається об'єкт person, який має дві властивості - name і age. Відповідно на консолі ми побачимо:

name
age 

Отримавши властивості і використовуючи спеціальний синтаксис об'єкт[властивість], ми можемо отримати значення кожної властивості:

const person = {ім'я: "Том", вік: 37};

for(prop in person){
console.log(prop, person[prop]);
}

Консольний вивід:

name Tom
age 37 

Цикл for...of

Цикл for...of призначений для перебору наборів даних. Наприклад, рядок являє собою фактично набір символів. І ми можемо перебрати його за допомогою цього циклу:

const text = "Hello";

for(char of text){
console.log(char);
}

У підсумку цикл перебирає всі символи рядка text і поміщає кожен поточний символ у змінну ch, значення якої потім виводиться на консоль.

H
e
l
l

Іншим прикладом може бути перебір масиву:

const people = ["Tom", "Sam", "Bob"];

for(const person of people) {
console.log(person);
}

У цьому випадку цикл перебирає елементи масиву people. Кожен елемент послідовно поміщається в константу person. І далі ми можемо вивести її значення на консоль:

Tom
Sam
Bob