При написании скриптов зачастую встает задача сделать однотипное действие много раз.
Например, вывести товары из списка один за другим. Или просто перебрать все числа от 1 до 10 и для каждого выполнить одинаковый код.
Для многократного повторения одного участка кода – предусмотрены циклы.
Цикл while
имеет вид:
Пока условие
верно – выполняется код из тела цикла.
Например, цикл ниже выводит i
пока i < 3
:
Повторение цикла по-научному называется «итерация». Цикл в примере выше совершает три итерации.
Если бы i++
в коде выше не было, то цикл выполнялся бы (в теории) вечно. На практике, браузер выведет сообщение о «зависшем» скрипте и посетитель его остановит.
Бесконечный цикл можно сделать и проще:
Условие в скобках интерпретируется как логическое значение, поэтому вместо while (i!=0)
обычно пишут while (i)
:
Проверку условия можно поставить под телом цикла, используя специальный синтаксис do..while
:
Цикл, описанный, таким образом, сначала выполняет тело, а затем проверяет условие.
Например:
Синтаксис do..while
редко используется, т.к. обычный while
нагляднее – в нём не приходится искать глазами условие и ломать голову, почему оно проверяется именно в конце.
Чаще всего применяется цикл for
. Выглядит он так:
Пример цикла, который выполняет alert(i)
для i
от 0
до 2
включительно (до 3
):
Здесь:
i=0
.i<3
.i++
.alert(i)
, т.е. код внутри фигурных скобок (они не обязательны, если только одна операция)Цикл выполняется так:
i=0
выполняется один-единственный раз, при заходе в цикл.i<3
проверяется перед каждой итерацией и при входе в цикл, если оно нарушено, то происходит выход.alert(i)
.i++
выполняется после тела на каждой итерации, но перед проверкой условия.Иными словами, поток выполнения: начало
→ (если условие
→ тело
→ шаг
) → (если условие
→ тело
→ шаг
) → … и так далее, пока верно условие
.
В цикле также можно определить переменную:
Эта переменная будет видна и за границами цикла, в частности, после окончания цикла i
станет равно 3
.
Любая часть for
может быть пропущена.
Например, можно убрать начало
. Цикл в примере ниже полностью идентичен приведённому выше:
Можно убрать и шаг
:
А можно и вообще убрать всё, получив бесконечный цикл:
При этом сами точки с запятой ;
обязательно должны присутствовать, иначе будет ошибка синтаксиса.
for..in
Существует также специальная конструкция for..in
для перебора свойств объекта.
Мы познакомимся с ней позже, когда будем говорить об объектах.
Выйти из цикла можно не только при проверке условия но и, вообще, в любой момент. Эту возможность обеспечивает директива break
.
Например, следующий код подсчитывает сумму вводимых чисел до тех пор, пока посетитель их вводит, а затем – выдаёт:
Директива break
в строке (*)
, если посетитель ничего не ввёл, полностью прекращает выполнение цикла и передаёт управление на строку за его телом, то есть на alert
.
Вообще, сочетание «бесконечный цикл + break» – отличная штука для тех ситуаций, когда условие, по которому нужно прерваться, находится не в начале-конце цикла, а посередине.
Директива continue
прекращает выполнение текущей итерации цикла.
Она – в некотором роде «младшая сестра» директивы break
: прерывает не весь цикл, а только текущее выполнение его тела, как будто оно закончилось.
Её используют, если понятно, что на текущем повторе цикла делать больше нечего.
Например, цикл ниже использует continue
, чтобы не выводить чётные значения:
Для чётных i
срабатывает continue
, выполнение тела прекращается и управление передаётся на следующий проход for
.
continue
позволяет обойтись без скобокЦикл, который обрабатывает только нечётные значения, мог бы выглядеть так:
С технической точки зрения он полностью идентичен. Действительно, вместо continue
можно просто завернуть действия в блок if
. Однако, мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри if
более длинный, то это ухудшает читаемость, в отличие от варианта с continue
.
Обычно мы можем заменить if
на оператор вопросительный знак '?'
.
То есть, запись:
…Аналогична записи:
В обоих случаях в зависимости от условия выполняется либо a()
либо b()
.
Но разница состоит в том, что оператор вопросительный знак '?'
, использованный во второй записи, возвращает значение.
Синтаксические конструкции, которые не возвращают значений, нельзя использовать в операторе '?'
.
К таким относятся большинство конструкций и, в частности, break/continue
.
Поэтому такой код приведёт к ошибке:
Впрочем, как уже говорилось ранее, оператор вопросительный знак '?'
не стоит использовать таким образом. Это – всего лишь ещё одна причина, почему для проверки условия предпочтителен if
.
Бывает нужно выйти одновременно из нескольких уровней цикла.
Например, внутри цикла по i
находится цикл по j
, и при выполнении некоторого условия мы бы хотели выйти из обоих циклов сразу:
В коде выше для этого использована метка.
Метка имеет вид "имя:"
, имя должно быть уникальным. Она ставится перед циклом, вот так:
Можно также выносить её на отдельную строку:
Вызов break outer
ищет ближайший внешний цикл с такой меткой и переходит в его конец.
В примере выше это означает, что будет разорван самый внешний цикл и управление перейдёт на alert
.
Директива continue
также может быть использована с меткой, в этом случае управление перепрыгнет на следующую итерацию цикла с меткой.
JavaScript поддерживает три вида циклов:
while
– проверка условия перед каждым выполнением.do..while
– проверка условия после каждого выполнения.for
– проверка условия перед каждым выполнением, а также дополнительные настройки.Чтобы организовать бесконечный цикл, используют конструкцию while(true)
. При этом он, как и любой другой цикл, может быть прерван директивой break
.
Если на данной итерации цикла делать больше ничего не надо, но полностью прекращать цикл не следует – используют директиву continue
.
Обе этих директивы поддерживают «метки», которые ставятся перед циклом. Метки – единственный способ для break/continue
повлиять на выполнение внешнего цикла.
Заметим, что метки не позволяют прыгнуть в произвольное место кода, в JavaScript нет такой возможности.