|
В этой статье приведен краткий обзор вариантов организации циклов по элементам массива на языке JavaScript.
[for...of — правильный выбор для массивов]
Этот цикл перебирает значения элементов. Работает с любыми итерируемыми объектами (массивы, строки, Map, Set, `arguments`, генераторы).
const fruits = ['яблоко', 'банан', 'вишня'];
for (const fruit of fruits) { console.log(fruit); // 'яблоко', 'банан', 'вишня'
}
Доступ к индексу через entries()
for (const [index, value] of fruits.entries()) { console.log(index, value); // 0 'яблоко', 1 'банан', 2 'вишня'
}
Операторы break, continue, return работают как обычно:
for (const fruit of fruits) { if (fruit === 'банан') continue; if (fruit === 'вишня') break; console.log(fruit); // 'яблоко'
}
[for...in — для массивов не рекомендуется]
Перебирает ключи (индексы в виде строк) и все перечисляемые свойства, включая унаследованные.
const arr = ['a', 'b', 'c'];
for (const key in arr) { console.log(key, typeof key); // '0' string, '1' string, '2' string console.log(arr[key]); // 'a', 'b', 'c'
}
Почему это опасно:
const arr = ['a', 'b', 'c'];
arr.customProp = 'проблема'; // добавили свойство Array.prototype.myMethod = () => {}; // или расширили прототип
for (const key in arr) { console.log(key); // '0', '1', '2', 'customProp', 'myMethod' ← лишнее!
}
Также порядок не гарантирован для нечисловых ключей, и это медленнее для массивов.
Сравнение for...of и for...in:
| Критерий |
for...of |
for...in |
| Что перебирает |
Значения |
Ключи (строки) |
| Для массивов |
✅ Рекомендуется |
❌ Не рекомендуется |
| Для объектов |
❌ (не итерируемы) |
✅ Рекомендуется |
| Учитывает доп. свойства |
Нет |
Да |
| Поддержка break/continue |
Да |
Да |
| Работает с Map/Set |
Да |
Нет |
Когда что использовать:
for...of — для массивов, строк, Map, Set, NodeList и любых итерируемых:
for (const ch of 'привет') console.log(ch); // по символам for (const [key, val] of new Map([['a', 1]])) console.log(key, val);
for...in — только для перебора свойств обычных объектов:
const user = { name: 'Иван', age: 30 };
for (const key in user) { if (Object.hasOwn(user, key)) { // защита от унаследованных свойств console.log(key, user[key]); }
}
[Альтернативы для массивов]
// Классический for — когда нужен индекс и максимальная производительность for (let i = 0; i < arr.length; i++) { /* ... */ }
// forEach — декларативно, но нельзя break
arr.forEach((value, index) => { /* ... */ });
Итог: для массивов используйте for...of (или forEach/классический for), а for...in оставьте для объектов. |