Пошук уроків, статей та іншого контенту
Навчіться перебирати значення масивів, рядків та інших ітерованих об'єктів за допомогою for...of. Розберіть, чому цей цикл часто зручніший за класичний for, коли індекс елемента не потрібен.
for...offor...of — це цикл JavaScript для перебору значень ітерованих об’єктів.
Найчастіше його використовують із:
масивами;
рядками;
множинами Set;
іншими об’єктами, які підтримують ітерацію.
Базовий синтаксис:
for (const value of iterable) {
// Дії для кожного значення
}На кожній ітерації змінна value отримує чергове значення з iterable.
const fruits = ["яблуко", "банан", "апельсин"];
for (const fruit of fruits) {
console.log(fruit);
}Результат:
яблуко
банан
апельсинЦикл самостійно:
починає перебір із першого елемента;
бере наступне значення;
виконує тіло циклу;
повторює ці дії, доки значення не закінчаться.
Під час перебору масиву змінна циклу містить безпосередньо значення елемента:
const numbers = [10, 20, 30, 40];
for (const number of numbers) {
console.log(number * 2);
}Результат:
20
40
60
80Якщо потрібно виконати однакову дію для кожного елемента, for...of часто зрозуміліший за класичний for.
forКласичний цикл:
const colors = ["червоний", "зелений", "синій"];
for (let index = 0; index < colors.length; index++) {
console.log(colors[index]);
}Цикл for...of:
const colors = ["червоний", "зелений", "синій"];
for (const color of colors) {
console.log(color);
}У другому варіанті не потрібно:
створювати змінну для індексу;
перевіряти індекс на кожній ітерації;
отримувати елемент через colors[index].
Тому for...of зручний, коли індекс елемента не потрібен.
Рядок також є ітерованим об’єктом. Цикл for...of перебирає його символи:
const word = "JavaScript";
for (const character of word) {
console.log(character);
}Результат:
J
a
v
a
S
c
r
i
p
tЦе можна використати, наприклад, щоб порахувати кількість голосних літер:
const text = "Програмування";
const vowels = "аеєиіїоуюя";
let vowelsCount = 0;
for (const character of text.toLowerCase()) {
if (vowels.includes(character)) {
vowelsCount++;
}
}
console.log(vowelsCount);Метод toLowerCase() переводить текст у нижній регістр, а includes() перевіряє, чи містить рядок певний символ або фрагмент.
breakОператор break повністю зупиняє цикл.
const numbers = [3, 7, 12, 5, 20];
for (const number of numbers) {
if (number > 10) {
console.log("Знайдено число більше 10:", number);
break;
}
console.log("Перевірка:", number);
}Результат:
Перевірка: 3
Перевірка: 7
Знайдено число більше 10: 12Після числа 12 цикл припиняється, тому значення 5 і 20 вже не перевіряються.
break зручно використовувати, коли потрібно знайти перший відповідний елемент.
continueОператор continue пропускає поточну ітерацію та переходить до наступної.
const numbers = [1, 2, 3, 4, 5, 6];
for (const number of numbers) {
if (number % 2 === 0) {
continue;
}
console.log(number);
}Результат:
1
3
5Парні числа пропускаються, а непарні виводяться.
SetSet зберігає унікальні значення. Його також можна перебирати за допомогою for...of.
const languages = new Set(["JavaScript", "Python", "JavaScript"]);
for (const language of languages) {
console.log(language);
}Результат:
JavaScript
PythonПовторне значення "JavaScript" не виводиться, оскільки Set зберігає лише унікальні значення.
MapMap зберігає пари «ключ — значення». За замовчуванням for...of повертає кожну пару як масив із двох елементів:
const users = new Map([
["Олена", 25],
["Андрій", 31],
["Марія", 28]
]);
for (const [name, age] of users) {
console.log(`${name}: ${age} років`);
}Результат:
Олена: 25 років
Андрій: 31 років
Марія: 28 роківСинтаксис [name, age] називається деструктуризацією масиву. Він одразу розкладає пару на дві змінні.
Окремо можна перебрати лише ключі або лише значення:
const scores = new Map([
["Олена", 90],
["Андрій", 85]
]);
for (const name of scores.keys()) {
console.log(name);
}
for (const score of scores.values()) {
console.log(score);
}for...of та for...inЦі цикли мають схожий запис, але призначені для різних завдань.
for...ofПеребирає значення:
const fruits = ["яблуко", "банан"];
for (const fruit of fruits) {
console.log(fruit);
}Результат:
яблуко
бананfor...inПеребирає ключі або індекси:
const fruits = ["яблуко", "банан"];
for (const index in fruits) {
console.log(index);
}Результат:
0
1Для масивів зазвичай краще використовувати for...of, якщо потрібні саме значення.
Якщо потрібні і значення, і індекси, можна використати метод entries():
const fruits = ["яблуко", "банан", "апельсин"];
for (const [index, fruit] of fruits.entries()) {
console.log(`${index}: ${fruit}`);
}Результат:
0: яблуко
1: банан
2: апельсинЗмінну циклу зазвичай оголошують через const:
const numbers = [1, 2, 3];
for (const number of numbers) {
console.log(number);
}На кожній ітерації створюється нове значення змінної number, тому const тут підходить.
Якщо потрібно змінювати окрему змінну-лічильник або інший стан, можна використовувати let:
const numbers = [2, 4, 6];
let total = 0;
for (const number of numbers) {
total += number;
}
console.log(total);Результат:
12Саму змінну number змінювати не потрібно. Змінюється змінна total, яка знаходиться поза циклом.
Звичайний об’єкт не можна безпосередньо перебрати за допомогою for...of:
const user = {
name: "Олена",
age: 25
};
// Такий код спричинить помилку:
// for (const value of user) {
// console.log(value);
// }Для отримання ключів або пар ключів і значень можна використати методи Object.keys(), Object.values() або Object.entries():
const user = {
name: "Олена",
age: 25,
city: "Львів"
};
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}Результат:
name: Олена
age: 25
city: ЛьвівObject.entries(user) створює масив пар:
[
["name", "Олена"],
["age", 25],
["city", "Львів"]
]Цей масив уже можна перебрати за допомогою for...of.
for...ofОбирайте for...of, коли:
потрібно перебрати значення масиву;
індекс елемента не має значення;
потрібно перебрати символи рядка;
потрібно перебрати значення Set або пари Map;
важлива зрозумілість і простота коду;
потрібно застосувати break або continue.
Класичний for більше підходить, коли:
потрібно працювати з індексом;
потрібно перебирати не всі елементи;
крок перебору відрізняється від одного;
потрібно рухатися масивом у зворотному напрямку.
const product = {
title: "Ноутбук",
price: 30000
};
// Помилка: звичайний об'єкт не є ітерованим
// for (const value of product) {
// console.log(value);
// }Використовуйте Object.entries(), Object.keys() або Object.values().
const names = ["Олена", "Андрій"];
for (const name of names) {
console.log(name);
}Тут name — це "Олена" або "Андрій", а не 0 або 1.
Якщо потрібні індекси:
for (const [index, name] of names.entries()) {
console.log(index, name);
}for...in для отримання значень масивуconst numbers = [10, 20, 30];
for (const index in numbers) {
console.log(index);
}Цей код виведе індекси. Для значень використовуйте:
for (const number of numbers) {
console.log(number);
}Не варто без потреби додавати або видаляти елементи з масиву всередині циклу. Це може зробити поведінку програми складнішою для розуміння.
Краще спочатку створити новий масив або виконати окрему операцію після завершення перебору.
Потрібно порахувати загальну вартість товарів у кошику:
const cart = [
{ name: "Книга", price: 300, quantity: 2 },
{ name: "Зошит", price: 50, quantity: 5 },
{ name: "Ручка", price: 25, quantity: 3 }
];
let total = 0;
for (const product of cart) {
const productTotal = product.price * product.quantity;
total += productTotal;
console.log(`${product.name}: ${productTotal} грн`);
}
console.log(`Загальна вартість: ${total} грн`);Результат:
Книга: 600 грн
Зошит: 250 грн
Ручка: 75 грн
Загальна вартість: 925 грнУ цьому прикладі індекси товарів не потрібні, тому for...of добре підходить для завдання.
for...of призначений для послідовного перебору значень ітерованих об’єктів.
Його основні переваги:
простий синтаксис;
відсутність ручної роботи з індексами;
зручний перебір масивів, рядків, Set і Map;
підтримка break і continue;
краща читабельність, коли індекс не потрібен.
for...of перебирає значення.
for...in перебирає ключі або індекси.
Для масиву без потреби в індексі зазвичай варто обирати for...of.
Для Map можна використовувати деструктуризацію [key, value].
Звичайні об’єкти потрібно спочатку перетворити через Object.entries(), Object.keys() або Object.values().
break зупиняє цикл, а continue пропускає поточну ітерацію.