Циклы в JavaScript (while, do ... while, for)

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

Также циклом может называться любая многократно исполняемая последовательность инструкций, организованная любым способом (например, с помощью условного перехода).

Одно выполнение тела цикла называется итерацией.

Виды циклов

Виды циклов:

  1. Безусловный (бесконечный) цикл - цикл, выход из которых не предусмотрен логикой программы. Специальных синтаксических средств для создания бесконечных циклов языки программирования не предусматривают, поэтому такие циклы создаются с помощью конструкций, предназначенных для создания обычных (или условных) циклов. Для обеспечения бесконечного повторения проверка условия в таком цикле либо отсутствует (если позволяет синтаксис), либо заменяется константным значением.
  2. Цикл с предусловием — цикл, который выполняется, пока истинно некоторое условие, указанное перед его началом. Это условие проверяется до выполнения тела цикла, поэтому тело может быть не выполнено ни разу (если условие с самого начала ложно). В большинстве процедурных языков программирования реализуется оператором while, отсюда его второе название — while-цикл.
  3. Цикл с постусловием — цикл, в котором условие проверяется после выполнения тела цикла. Отсюда следует, что тело всегда выполняется хотя бы один раз.
  4. Цикл с выходом из середины — наиболее общая форма условного цикла. Синтаксически такой цикл оформляется с помощью трёх конструкций:
    • начала цикла (маркирует точку программы, в которой начинается тело цикла);
    • конца цикла (маркирует точку, где тело заканчивается);
    • команды выхода из цикла (при выполнении которой цикл заканчивается и управление передаётся на оператор, следующий за конструкцией конца цикла). Для того чтобы цикл выполнился более одного раза, команда выхода должна вызываться не безусловно, а только при выполнении условия выхода из цикла.
  5. Цикл со счётчиком — цикл, в котором некоторая переменная изменяет своё значение от заданного начального значения до конечного значения с некоторым шагом, и для каждого значения этой переменной тело цикла выполняется один раз. В большинстве процедурных языков программирования реализуется оператором for, в котором указывается счётчик (так называемая «переменная цикла»), требуемое количество проходов (или граничное значение счётчика) и, возможно, шаг, с которым изменяется счётчик.
  6. Совместный цикл (цикл по коллекции, цикл просмотра) - цикл, задающий выполнение некоторой операции для объектов из заданного множества, без явного указания порядка перечисления этих объектов. Совместный цикл, теоретически, никак не определяет, в каком порядке операция будет применяться к элементам множества, хотя конкретные языки программирования, разумеется, могут задавать конкретный порядок перебора элементов. Произвольность даёт возможность оптимизации исполнения цикла за счёт организации доступа не в заданном программистом, а в наиболее выгодном порядке.

Замечание: принципиальное отличие цикла с выходом из середины от других условных циклов:

  • часть тела цикла, расположенная после начала цикла и до команды выхода, выполняется всегда (даже если условие выхода из цикла истинно при первой итерации);
  • часть тела цикла, находящаяся после команды выхода, не выполняется при последней итерации.

[свернуть]

Цикл while

Цикл while имеет следующий синтаксис:

Код из тела цикла выполняется, пока условие condition истинно (true).

Условием цикла может быть любое выражение или переменная: условие while вычисляется и преобразуется в логическое значение.

Примеры

[свернуть]

Тело цикла из одной строки (из одной инструкции) не требует фигурных скобок {…}:

Цикл do … while

Обеспечивает проверку условия, расположенного под телом цикла. Сначала выполняется тело цикла, а затем проверяется условие condition: пока его значение равно true, тело цикла выполняется снова и снова.

Форма цикла do ... while оправдана, если вы хотите чтобы тело цикла выполнилось хотя бы один раз, даже если условие окажется ложным. На практике чаще используется форма с предусловием: while(…) {…}.

Цикл for

Цикл for состоит из 3 необязательных выражений в круглых скобках, разделённых точками с запятой, и имеет следующий синтаксис:

Алгоритм работы цикла for

  1. [инициализация]
  2. [условие] (true)
  3. тело цикла
  4. [финальное выражение]
  5. [условие] (true) ... 
  6. тело цикла
  7. [финальное выражение]
  8. [условие] (false)  
  9. end.

[свернуть]

Инициализация - это выражение (в том числе выражения присвоения) или определение переменных. Обычно используется:

  • для инициализации счётчика (если переменная была объявлена выше по коду);
  • для встроенного (опционального) объявления новых переменных с помощью ключевого слова:
    1. var - видимы вне цикла в той же области области видимости, что и цикл for;
    2. let - видимы только внутри цикла.

Результат выражения [инициализация] отбрасывается.

Условие - это выражение, выполняющееся на каждой итерации цикла:

  • если [условие] истинно, цикл выполняется;
  • если выражения [условие] нет, то условие всегда считается истиной.
  • если [условие] ложно, выполнение переходит к первому выражению, следующему за for.

Условие не является обязательным.

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

Тело цикла - выражение, которое выполняется, когда условие цикла истинно. Чтоб выполнить множество выражений в цикле, используется блок ({ ... }) для группировки этих выражений. Чтобы не выполнять никакого выражения в цикле, используется пустое выражение (;).

Любая часть цикла for может быть пропущена, при этом сами точки с запятой ";" при записи обязательны (иначе будет ошибка синтаксиса).

Примеры

[свернуть]
Ключевое слово var в циклах

Переменная, объявленная в заголовке цикла for с помощью ключевого слова var – одна на все итерации цикла: она не может быть блочной или локальной внутри цикла и видна даже после выполнения цикла:

[свернуть]
Ключевое слово let в циклах

Переменная, объявленная в заголовке цикла for с помощью ключевого слова let, будет объявлена для каждой итерации (а не один раз для всего цикла). Каждому повторению цикла соответствует своя независимая переменная let. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой из них будет та переменная, которая была при соответствующей итерации:

[свернуть]

Перебор символов строки с помощью цикла for:

Перебор элементов массива циклом for:

Прерывание цикла «break»

Директива break позволяет выйти из цикла в любой момент: она полностью прекращает выполнение цикла и передаёт управление на строку за его телом.

Сочетание «бесконечный цикл + break» используется в ситуациях, когда условие, по которому нужно прерваться, находится не в начале или конце цикла, а посередине.

Переход к следующей итерации "continue"

Директива continue – это «облегчённая версия» break.

По сравнению с инструкцией break, continue прерывает выполнение цикла не полностью:

  • в цикле while оно переносит поток выполнения к условию;
  • в цикле for оно переносит поток выполнения к финальному выражению в описании цикла.

Таким образом, при её выполнении цикл не прерывается, а переходит к следующей итерации (если условие все ещё равно true).

Директива continue позволяет избегать вложенности.

Нельзя использовать break/continue справа от оператора „?“.

Метки для break/continue

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

Метка – это именованный идентификатор, располагающийся выше цикла и позволяющий выйти из цикла (вложенного уровня сложного цикла) в начало цикла на строку с указанным идентификатором.

Вызов break Outer в цикле ниже ищет ближайший внешний цикл с такой меткой и переходит в его конец.

В примере выше это означает, что вызовом break Outer будет разорван внешний цикл до метки с именем Outer, и управление перейдёт к строке alert('Готово!').

Можно размещать метку на отдельной строке:

Директива continue также может быть использована с меткой. В этом случае управление перейдёт на следующую итерацию цикла с меткой.

Метки не дают возможности передавать управление в произвольное место кода.

Вызов директив break и continue возможен только внутри цикла, а метка должна находиться в коде выше этих директив.

Цикл for ... in и for ... of 

Цикл for … in

Цикл for … in применяется для перебора всех перечисляемых свойств объекта, и имеет следующий синтаксис:

  • key - переменная, получающая очередное имя свойства, назначаемое на каждой итерации;
  • object -  объект, свойства которого перебираются циклом.

Пример:

Еще примеры

[свернуть]

Цикл for...in проходит только по перечисляемым свойствам объекта в произвольном порядке: for...in не следует использовать для Array, где важен порядок индексов (с числовыми свойствами или индексами массивов, когда важен порядок доступа к свойствам, лучше использовать циклы for, Array.prototype.forEach() или for...of). Свойства, добавленные в объект при выполнении цикла, могут быть пропущены. Не следует добавлять, изменять или удалять свойство объекта во время итерации (если цикл по нему ещё не прошёл).

Объекты, созданные встроенными конструкторами, такими как Array и Object имеют неперечисляемые свойства от Object.prototype и String.prototype, например, от String - это indexOf(), а от Object - метод toString(). Цикл пройдёт по всем перечисляемым свойствам объекта, а также тем, что он унаследует от конструктора прототипа (свойства объекта в цепи прототипа). Подробнее о перечисляемых и не перечисляемых свойствах.

Для получения массива со всеми свойствами объекта (независимо от того, перечисляемые они или нет) используйте метод Reflect.ownKeys() или getOwnPropertyNames()

Пример использования методов getOwnPropertyNames() и Reflect.ownKeys()

[свернуть]
Примеры

[свернуть]

Цикл for...of

Оператор for...of выполняет цикл обхода итерируемых объектов (включая Array, Map, Set, объект arguments и подобных), вызывая на каждом шаге итерации  значения для каждого свойства объекта.

Подробнее об итерируемых объектах и итераторе.

Синтаксис цикла for...of:

  • variable - на каждом шаге итерации переменной variable присваивается значение нового свойства итерируемого объекта object (переменная variable может быть объявлена с помощью const, let или var);
  • object - объект, перечисляемые свойства которого обходятся во время выполнения цикла.

Если объект неитерируемый, движок вернет ошибку "... is not iterable".

Пример

 

[свернуть]

Примеры использования цикла for...of:

Обход массива (Array)

Допускается использовать const вместо let, если не нужно переназначать переменные (изменять значения элементов массива) внутри цикла:

[свернуть]
Обход строки (String)

[свернуть]
Обход Map

[свернуть]
Обход Set

[свернуть]
Обход объекта arguments

[свернуть]
Обход DОM коллекций

Обход DOM коллекций наподобие NodeList. Следующий пример добавляет класс read параграфам, являющимся непосредственными потомками статей:

[свернуть]

В циклах for...of аварийный выход осуществляется через break, throw или return. Во всех вариантах итератор завершается.

Пример использования циклов for ... in и for ... of: 

 

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.