Базовый курс JavaScript
-
1. Вступление. Подготовка к работе. console.log
-
2. Типы данных, операторы, методы и свойства
-
3. Динамическая типизация. Условия if, swith
-
4. Логические операторы. Функции
-
5. Функции declaration/expression. Область видимости
-
6. Объекты, массивы
-
7. Циклы while и for
-
8. Методы массивов
-
Практика 1.
-
10. Доступ к элементам в DOM. Доступ к элементам
-
11. Изменение документа. Практика: Галерея
-
12. Добавление событий
-
13. Всплытие и погружение. Объект события.
-
14. Объект Math. localStorage
-
15. Практика
-
16. Дата. This
-
17. Асинхронность js. Promise.
-
18. Практика
7. Циклы while и for
Циклы while и for
При написании скриптов зачастую встаёт задача сделать однотипное действие много раз.
Например, вывести товары из списка один за другим. Или просто перебрать все числа от 1
до 10
и для каждого выполнить одинаковый код.
Для многократного повторения одного участка кода предусмотрены циклы.
Небольшое объявление для продвинутых читателей.
В этой статье рассматриваются только базовые циклы: while
, do..while
и for(..;..;..)
.
Если вы пришли к этой статье в поисках других типов циклов, вот указатели:
- См. for…in для перебора свойств объекта.
- См. for…of и Перебираемые объекты для перебора массивов и перебираемых объектов.
В противном случае, продолжайте читать.
Цикл «while»
Цикл while
имеет следующий синтаксис:
while (condition) {
// код
// также называемый "телом цикла"
}
Код из тела цикла выполняется, пока условие condition
истинно.
Например, цикл ниже выводит i
, пока i < 3
:
let i = 0;
while (i < 3) { // выводит 0, затем 1, затем 2
alert( i );
i++;
}
Одно выполнение тела цикла по-научному называется итерация. Цикл в примере выше совершает три итерации.
Если бы строка i++
отсутствовала в примере выше, то цикл бы повторялся (в теории) вечно. На практике, конечно, браузер не позволит такому случиться, он предоставит пользователю возможность остановить «подвисший» скрипт, а JavaScript на стороне сервера придётся «убить» процесс.
Любое выражение или переменная может быть условием цикла, а не только сравнение: условие while
вычисляется и преобразуется в логическое значение.
Например, while (i)
– более краткий вариант while (i != 0)
:
let i = 3;
while (i) { // когда i будет равно 0, условие станет ложным, и цикл остановится
alert( i );
i--;
}
Если тело цикла состоит лишь из одной инструкции, мы можем опустить фигурные скобки {…}
:
let i = 3;
while (i) alert(i--);
Цикл «do…while»
Проверку условия можно разместить под телом цикла, используя специальный синтаксис do..while
:
do {
// тело цикла
} while (condition);
Цикл сначала выполнит тело, а затем проверит условие condition
, и пока его значение равно true
, он будет выполняться снова и снова.
Например:
let i = 0;
do {
alert( i );
i++;
} while (i < 3);
Такая форма синтаксиса оправдана, если вы хотите, чтобы тело цикла выполнилось хотя бы один раз, даже если условие окажется ложным. На практике чаще используется форма с предусловием: while(…) {…}
.
Цикл «for»
Более сложный, но при этом самый распространённый цикл — цикл for
.
Выглядит он так:
for (начало; условие; шаг) {
// ... тело цикла ...
}
Давайте разберёмся, что означает каждая часть, на примере. Цикл ниже выполняет alert(i)
для i
от 0
до (но не включая) 3
:
for (let i = 0; i < 3; i++) { // выведет 0, затем 1, затем 2
alert(i);
}
Рассмотрим конструкцию for
подробней:
часть | ||
---|---|---|
начало | let i = 0 | Выполняется один раз при входе в цикл |
условие | i < 3 | Проверяется перед каждой итерацией цикла. Если оно вычислится в false , цикл остановится. |
тело | alert(i) | Выполняется снова и снова, пока условие вычисляется в true . |
шаг | i++ | Выполняется после тела цикла на каждой итерации перед проверкой условия. |
В целом, алгоритм работы цикла выглядит следующим образом:
Выполнить начало
→ (Если условие == true → Выполнить тело, Выполнить шаг)
→ (Если условие == true → Выполнить тело, Выполнить шаг)
→ (Если условие == true → Выполнить тело, Выполнить шаг)
→ ...
То есть, начало
выполняется один раз, а затем каждая итерация заключается в проверке условия
, после которой выполняется тело
и шаг
.
Если тема циклов для вас нова, может быть полезным вернуться к примеру выше и воспроизвести его работу на листе бумаги, шаг за шагом.
Вот в точности то, что происходит в нашем случае:
// for (let i = 0; i < 3; i++) alert(i)
// Выполнить начало
let i = 0;
// Если условие == true → Выполнить тело, Выполнить шаг
if (i < 3) { alert(i); i++ }
// Если условие == true → Выполнить тело, Выполнить шаг
if (i < 3) { alert(i); i++ }
// Если условие == true → Выполнить тело, Выполнить шаг
if (i < 3) { alert(i); i++ }
// ...конец, потому что теперь i == 3
В примере переменная счётчика i
была объявлена прямо в цикле. Это так называемое «встроенное» объявление переменной. Такие переменные существуют только внутри цикла.
for (let i = 0; i < 3; i++) {
alert(i); // 0, 1, 2
}
alert(i); // ошибка, нет такой переменной
Вместо объявления новой переменной мы можем использовать уже существующую:
let i = 0;
for (i = 0; i < 3; i++) { // используем существующую переменную
alert(i); // 0, 1, 2
}
alert(i); // 3, переменная доступна, т.к. была объявлена снаружи цикла
Пропуск частей «for»
Любая часть for
может быть пропущена.
Для примера, мы можем пропустить начало
если нам ничего не нужно делать перед стартом цикла.
Вот так:
let i = 0; // мы уже имеем объявленную i с присвоенным значением
for (; i < 3; i++) { // нет необходимости в "начале"
alert( i ); // 0, 1, 2
}
Можно убрать и шаг
:
let i = 0;
for (; i < 3;) {
alert( i++ );
}
Это сделает цикл аналогичным while (i < 3)
.
А можно и вообще убрать всё, получив бесконечный цикл:
for (;;) {
// будет выполняться вечно
}
При этом сами точки с запятой ;
обязательно должны присутствовать, иначе будет ошибка синтаксиса.
Прерывание цикла: «break»
Обычно цикл завершается при вычислении условия в false
.
Но мы можем выйти из цикла в любой момент с помощью специальной директивы break
.
Например, следующий код подсчитывает сумму вводимых чисел до тех пор, пока посетитель их вводит, а затем – выдаёт:
let sum = 0;
while (true) {
let value = +prompt("Введите число", '');
if (!value) break; // (*)
sum += value;
}
alert( 'Сумма: ' + sum );
Директива break
в строке (*)
полностью прекращает выполнение цикла и передаёт управление на строку за его телом, то есть на alert
.
Вообще, сочетание «бесконечный цикл + break
» – отличная штука для тех ситуаций, когда условие, по которому нужно прерваться, находится не в начале или конце цикла, а посередине или даже в нескольких местах его тела.
Переход к следующей итерации: continue
Директива continue
– «облегчённая версия» break
. При её выполнении цикл не прерывается, а переходит к следующей итерации (если условие все ещё равно true
).
Её используют, если понятно, что на текущем повторе цикла делать больше нечего.
Например, цикл ниже использует continue
, чтобы выводить только нечётные значения:
for (let i = 0; i < 10; i++) {
// если true, пропустить оставшуюся часть тела цикла
if (i % 2 == 0) continue;
alert(i); // 1, затем 3, 5, 7, 9
}
Для чётных значений i
, директива continue
прекращает выполнение тела цикла и передаёт управление на следующую итерацию for
(со следующим числом). Таким образом alert
вызывается только для нечётных значений.
continue
позволяет избегать вложенностиЦикл, который обрабатывает только нечётные значения, мог бы выглядеть так:
for (let i = 0; i < 10; i++) {
if (i % 2) {
alert( i );
}
}
С технической точки зрения он полностью идентичен. Действительно, вместо continue
можно просто завернуть действия в блок if
.
Однако мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри if
более длинный, то это ухудшает читаемость, в отличие от варианта с continue
.
Задание
- С помощью цикла
for
выведите в консоль четные числа в промежутке от0
до100
. - С помощью цикла
for
выведите в консоль числа от100
до0
. Выведите в консоль все элементы следующего массива, за исключением нулевого и последнего:
let arr = ['a', 'b', 'c', 'd', 'e'];