Read 5 min
Использование циклов в JS
Базовые циклы for, while, do...while
Есть 3 базовых конструкции которые существуют с самых ранних стандартов ECMAScript и позволяют осуществлять итерацию по структурам данных:
for- наиболее часто распространенная конструкцияdo...while- используется крайне редко, обычно предпочтение отдается в пользуforwhile- используется редко, обычно предпочтение отдается в пользуfor
C их помощью можно итерировать различные структуры данных, например массивы:
Цикл for
const arr = ['a', 'b', 'c'];
for (let index = 0; index < arr.length; index++) {
console.log(arr[index]);
} Цикл while
const arr = ['a', 'b', 'c'];
let index = 0;
while (index < arr.length) {
console.log(arr[index]);
index++;
} Цикл do...while
const arr = ['a', 'b', 'c'];
let index = 0;
do {
console.log(arr[index]);
} while (++index < arr.length);Однако, данные циклы неудобны тем, что приходится вручную объявлять переменные index увеличивать их index++, следить за условием index < arr.length
Более того, если допустить ошибку есть вероятность влипнуть в бесконечный цикл при использовании while и do...while, а это отберет у вас драгоценное время разработки, которое вы потратите на то чтобы убить вкладку браузера, если конечно он не сделает это за вас, через какое-то время, но это не точно :)
Итерируемые структуры данных
Итерация с помощью метода forEach
Для итерации по массивам и некоторым другим коллекциям данных можно использовать встроенный метод forEach
const arr = ['a', 'b', 'c'];
arr.forEach((item, index) => {
console.log(item);
});Но у данного метода есть недостаток - он не поддерживает управляющие конструкции break и continue, и return false также не оборвет итерацию, поэтому следует использовать данный метод только в том случае когда нет необходимости оборвать процесс итерации
Чтобы исправить положение связанное с невозможностью использования break и continue на помощь приходит цикл for...of
Итерация с помощью метода for...of
Данный цикл появился с приходом стандарта ECMAScript 2015 (ES6) и позволяет итерировать различные структуры данных: массивы, Map/WeackMap, Set/WeackSet, NodeList
const arr = ['a', 'b', 'c'];
for (const item of arr) {
console.log(item);
}Более того, он поддерживает управляющие конструкции break и continue,
а итерация происходит по собственным перечисляемым свойствам итерируемых объектов.
И все бы хорошо, но как заметно из сигнатуры данного цикла, в нем нет возможности использовать индекс итерируемых данныx.
Для решения данной проблемы можно использовать встроенный метод массива entries:
for (const [index, value] of ['a', 'b', 'c'].entries()) {
console.log(index, value);
}Итерация по свойствам объектов
Итерация с помощью метода for...in
Для итерации по объектам можно применять цикл for...in, но у него есть ряд недостатков:
-
перебор происходит по алгоритму: "сначала целочисленные свойства, затем свойства в порядке добавления" - подробнее тут
-
в отличии от
for...ofон перебирает все свойства объектов как собственные так и унаследованные
const parent = {
color: 'red'
};
const child = {
fruite: 'apple'
};
child.__proto__ = parent;
for (const prop in child) {
console.log(child[prop]);
}
// 'apple'
// 'red'Чтобы исправить, можно добавить проверку с использование метода hasOwnProperty который проверит собственное ли свойства:
const parent = {
color: 'red'
};
const child = {
fruite: 'apple'
};
child.__proto__ = parent;
for (const prop in child) {
if (child.hasOwnProperty(prop)) {
console.log(child[prop]);
}
}
// 'apple'Но лучше отдавать предпочтение для итерации по объектам c помощью for...of в связке с одним из методов:
Object.keysObject.valuesObject.entries
Они возвращают массив только собственных значений объекта:
for (const [key, value] of Object.entries(obj)) { /* logic */}
for (const key of Object.keys(obj)) { /* logic */ }
for (const value of Object.values(obj)) { /* logic */ }Вывод:
На практике целесообразно использовать следующие циклы:
forEach- если нет необходимости "оборвать" итерациюfor...ofво всех других случаях, в том числе и для итерации по объектам