Одна из первых проблем, которую вам нужно научиться преодолевать при обучении программированию, - это избегать печально известных ошибок копирования и вставки. В программировании есть известная аббревиатура D.R.Y., что означает «не повторяйся». Как и все остальное, это можно довести до крайности, но это твердый принцип, не зря выдержавший испытание временем.

Существует множество шаблонов, которые помогут вам не повторяться, и один из самых основных шаблонов, встроенных во все языки программирования, - это цикл. Существует два разных цикла, которые любой программист должен использовать при написании кода: циклы, в которых количество итераций известно заранее, и циклы, в которых количество итераций заранее неизвестно. (Для ясности, номер может быть неизвестен до тех пор, пока программа не будет запущена, но если он известен до начала цикла, он подходит для первой категории, в противном случае он подходит для второй категории.)

Интересно, что в JavaScript есть два способа создания циклов для решения этих двух ситуаций. Эти два цикла обычно называются «циклами For» и «while» по очевидным причинам, которые вы скоро увидите. В этом посте я подумал, что расскажу об основах написания этих циклов и их вариантах использования. (Прежде чем кто-либо будет жаловаться, я понимаю, что технически существует более двух способов создания циклов. Все циклы являются вариациями цикла For или цикла While, которые используются для тех же случаев использования, что и те, о которых я расскажу здесь.)

Пока цикл

Цикл while, вероятно, является самой простой формой цикла. Цикл while очень похож на оператор if, как синтаксически, так и с точки зрения использования. Основная форма оператора if: если какое-то условие истинно, запустите этот код, например:

if (condition) {
   // this code runs only if
   // the above condition is true
}

Циклы while выглядят почти так же:

while (condition) {
   // this code runs only if
   // the above condition is true
   // and it will continue to run
   // while it is true
}

Самая большая разница между этими двумя примерами, помимо использования слова while вместо if,, заключается в том, что цикл while будет продолжать проверять условие после запуска кода, и если оно истинно, он будет запущен снова.

Предположим, вам нужно проанализировать некоторую строку и найти все индексы определенной подстроки. Поскольку невозможно узнать, сколько экземпляров этой подстроки, мы можем использовать цикл while, чтобы просмотреть строку следующим образом:

let indexes = [];
let currentIndex = stringToParse.indexOf(sring,0);
while (currentIndex !== -1){
   indexes.push(currentIndex)
 
   currentIndex = 
        stringToParse.indexOf(sring, currentIndex+1)
 
}

В приведенном выше примере инициализируется currentIndex, а затем проверяется, не равно ли его значение -1, что указывает на отсутствие экземпляра этой подстроки, а затем этот индекс помещается в массив индексов. Затем он ищет следующий индекс. Если индекс по-прежнему не равен -1, он будет повторяться до тех пор, пока не изменится.

Самая большая проблема, о которой нужно знать, - это возможность непреднамеренного создания бесконечного цикла. Если вы неправильно создадите ситуацию, которая выйдет из цикла, ваш код застрянет в цикле и, вероятно, выйдет из строя.

Существует разновидность цикла while, называемая циклом do / while. Этот цикл сначала запустит код в блоке, а затем проверит условие, например:

do {
   // this code runs once, but unless
   // the below condition is true
   // and it will not continue to run
} while (condition);

Допустим, вам нужно получить ввод пользователя, а затем продолжить, только если ввод действителен. Эту логику можно было бы записать так:

let userInput;
let isValidInput = true;
do {
   userInput = getInput();
   isValidInput = verify(userInput)
   if(!isValidInput) sendMessage("Please enter Valid Input")
} while (!isValidInput);

Мы всегда знаем, что хотим получить ввод от клиента, и не будем знать, нужно ли нам зацикливаться, пока не получим ввод от клиента. Это прекрасный пример того, когда использовать цикл do / while.

Для циклов

Другая ситуация, когда может потребоваться цикл, - это когда у вас есть конечное количество запусков. Чтобы сделать это с помощью цикла while, вы должны написать его так:

let i = 0;
while (i < 3) {
   // this code will run
   // only 3 times
   i++;
}

Как видите, есть три части, которые заставляют его работать: инициализация, условие цикла и приращение. Вот тот же пример, но с пометкой, чтобы выделить эти 3 части:

let i = 0; // the initialization
while (i < 3) { // the condition
   ...
   i++; // the incrementation
}

Этот процесс настолько рутинен, что они встроили его в язык с помощью цикла for. Нравится:

for(initialization; condition; incrementation){
   ...
}

В приведенном выше примере важно помнить, что каждая область разделяется точкой с запятой, а не запятой. Я потратил много времени, пытаясь выяснить, что мой код выдает ошибку, только чтобы узнать, что я использовал запятую вместо точки с запятой.

Итак, мы можем переписать наш цикл while следующим образом:

for(let i = 0; i < 3; i++){
   // this code will run
   // only 3 times
}

Скажем, нам нужно получить три ввода от пользователя и поместить их в массив. Мы могли бы написать это так:

let userInputArr = [];
for(let i = 0; i < 3; i++){
   const input = getInput();
   
   userInputArr.push(input);
}

В JavaScript есть два варианта цикла for, а именно цикл for / in и, начиная с ES6, цикл for / of. Циклы For / in предназначены для перебора традиционных объектов javascript. В циклах For / in нет трех разделов, как в цикле for, вместо этого вы объявляете переменную in и свой объект. Например:

const myObj = { a:1, b:2, c:3 };
for(let key in myObj){
  // key will be 'a', then 'b', then 'c'
}

При использовании циклов for / in с массивами важно отметить, что «ключ» массива - это просто индекс. Таким образом, при использовании цикла for / in с массивом вы не получите значение по каждому индексу, вместо этого вы получите индекс.

Цикл for / of - недавнее дополнение, специально предназначенное для итерации по итерируемым объектам, таким как массивы, строки, карты и наборы. Синтаксически он почти идентичен циклу for / in, за исключением того, что вы заменяете in на of.. Функционально они разные. Вместо получения ключа, как в цикле for / in, вы получаете фактическое значение в этом месте. Например:

const greeting = "Hi!";
for(let char of greeting){
   //char = "H" then "i" and then "!";
}

Важно, чтобы для массивов, как я сказал в своем посте о методах массива, циклы for НЕ должны быть вашим основным решением для итерации по массивам. Вместо этого следует использовать map, filter, reduce, or forEach. При этом ЕСЛИ вы определили, что у вас проблема с производительностью. И ваш метод массива является причиной этой проблемы, тогда преобразование вашего кода в цикл for является одним из способов чтобы улучшить эту производительность.

Цикл - важная стратегия улучшения ремонтопригодности вашего кода. Знание того, какой тип цикла и как его использовать, является важным шагом на пути к тому, чтобы вы научились создавать потрясающий код на JavaScript.