Циклы
Чтобы понять действие условных операторов, мы предлагали представить их в виде разветвлений на дороге, по которой двигается интерпретатор JavaScript. Циклы можно представить как разворот на дороге, возвращающий обратно, который заставляет интерпретатор многократно проходить через один и тот же участок программного кода.
В языке JavaScript имеется четыре цикла: while, do/while, for и for/in. Каждому из них посвящен один из следующих подразделов. Одно из обычных применений циклов — обход элементов массива.
Цикл while
Оператор if является базовым условным оператором в языке JavaScript, а базовым циклом для JavaScript можно считать цикл while. Он имеет следующий синтаксис:
while (выражение)
Цикл while начинает работу с вычисления выражения. Если это выражение имеет ложное значение, интерпретатор пропускает инструкцию, составляющую тело цикла, и переходит к следующей инструкции в программе. Если выражение имеет истинное значение, то выполняется инструкция, образующая тело цикла, затем управление передается в начало цикла и выражение вычисляется снова. Иными словами, интерпретатор снова и снова выполняет инструкцию тела цикла, пока значение выражения остается истинным. Обратите внимание, что имеется возможность организовать бесконечный цикл с помощью синтаксиса while(true).
Обычно не требуется, чтобы интерпретатор JavaScript снова и снова выполнял одну и ту же операцию. Почти в каждом цикле с каждой итерацией цикла одна или несколько переменных изменяют свои значения. Поскольку переменная меняется, действия, которые выполняет инструкция, при каждом проходе тела цикла могут отличаться.
Кроме того, если изменяемая переменная (или переменные) присутствует в выражении, значение выражения может меняться при каждом проходе цикла. Это важно, т.к. в противном случае выражение, значение которого было истинным, никогда не изменится и цикл никогда не завершится! Ниже приводится пример цикла while, который выводит числа от 0 до 9:
var count = 0; while (count
Как видите, в начале переменной count присваивается значение 0, а затем ее значение увеличивается каждый раз, когда выполняется тело цикла. После того как цикл будет выполнен 10 раз, выражение вернет false (т.е. переменная count уже не меньше 10), инструкция while завершится и интерпретатор перейдет к следующей инструкции в программе. Большинство циклов имеют переменные-счетчики, аналогичные count. Чаще всего в качестве счетчиков цикла выступают переменные с именами i, j и k, хотя для того чтобы сделать программный код более понятным, следует давать счетчикам более наглядные имена.
Цикл do/while
Цикл do/while во многом похож на цикл while, за исключением того, что выражение цикла проверяется в конце, а не в начале. Это значит, что тело цикла всегда выполняется как минимум один раз. Эта инструкция имеет следующий синтаксис:
do < инструкция >while (выражение);
Цикл do/while используется реже, чем родственный ему цикл while. Дело в том, что на практике ситуация, когда вы заранее уверены, что потребуется хотя бы один раз выполнить тело цикла, несколько необычна. Ниже приводится пример использования цикла do/while:
function printArray(a) < var len = a.length, i = 0; if (len == 0) console.log("Пустой массив"); else < do < console.log(a[i]); >while (++i < len); >> printArray([1,5,6,8]);
Между циклом do/while и обычным циклом while имеется два отличия. Во-первых, цикл do требует как ключевого слова do (для отметки начала цикла), так и ключевого слова while (для отметки конца цикла и указания условия). Во-вторых, в отличие от цикла while, цикл do завершается точкой с запятой. Цикл while необязательно завершать точкой с запятой, если тело цикла заключено в фигурные скобки.
Цикл for
Цикл for представляет собой конструкцию цикла, которая часто оказывается более удобной, чем цикл while. Цикл for упрощает конструирование циклов, следующих шаблону, общему для большинства циклов. Большинство циклов имеют некоторую переменную-счетчик. Эта переменная инициализируется перед началом цикла и проверяется перед каждой итерацией. Наконец, переменная-счетчик инкрементируется или изменяется каким-либо другим образом в конце тела цикла, непосредственно перед повторной проверкой переменной. Инициализация, проверка и обновление — это три ключевых операции, выполняемых с переменной цикла. Инструкция for делает эти три шага явной частью синтаксиса цикла:
for(инициализация; проверка; инкремент)
Инициализация, проверка и инкремент — это три выражения (разделенных точкой с запятой), которые ответственны за инициализацию, проверку и увеличение переменной цикла. Расположение их в первой строке цикла упрощает понимание того, что делает цикл for, и не позволяет забыть инициализировать или увеличить переменную цикла.
Проще всего объяснить работу цикла for, показав эквивалентный ему цикл while:
инициализация; while(проверка)
Другими словами, выражение инициализации вычисляется один раз перед началом цикла. Это выражение, как правило, является выражением с побочными эффектами (обычно присваиванием). В JavaScript также допускается, чтобы выражение инициализации было инструкцией объявления переменной var, поэтому можно одновременно объявить и инициализировать счетчик цикла.
Выражение проверки вычисляется перед каждой итерацией и определяет, будет ли выполняться тело цикла. Если результатом проверки является истинное значение, выполняется инструкция, являющаяся телом цикла. В конце цикла вычисляется выражение инкремент. Чтобы использование этого выражения имело смысл, оно должно быть выражением с побочными эффектами. Обычно это либо выражение присваивания, либо выражение, использующее оператор ++ или —.
Вывести числа от 0 до 9 можно также с помощью цикла for, как показано ниже, в противовес эквивалентному циклу while, показанному в примере ранее:
for (var count = 0; count < 10; count++) console.log(count);
Конечно, циклы могут быть значительно более сложными, чем в этих простых примерах, и иногда в каждой итерации цикла изменяется несколько переменных. Эта ситуация - единственный случай в JavaScript, когда часто применяется оператор «запятая» - он позволяет объединить несколько выражений инициализации и инкрементирования в одно выражение, подходящее для использования в цикле for:
var i,j; for (i = 0, j = 0; i < 10; i++, j++) // Выведет в консоли таблицу квадратов чисел от 0 - 9 console.log('%s * %s = %s', i, j, i*j);
Цикл for/in
Цикл for/in использует ключевое слово for, но он в корне отличается от обычного цикла for. Цикл for/in имеет следующий синтаксис:
for (переменная in объект)
В качестве переменной здесь обычно используется имя переменной, но точно так же можно использовать инструкцию var, объявляющую единственную переменную. Параметр объект - это выражение, возвращающее объект. И как обычно, инструкция - это инструкция или блок инструкций, образующих тело цикла.
Для обхода элементов массива естественно использовать обычный цикл for:
var arr = [1,2,3,4,5]; for (var i = 0; i < arr.length; i++) < // Присваивать индексы в массиве переменной i console.log(arr[i]); // Вывести значение каждого элемента массива >
Инструкция for/in так же естественно позволяет выполнить обход свойств объекта:
// Создадим новый объект var obj = ; for (var i in obj) < // Вывести значение каждого свойства объекта console.log(obj[i]); >
Чтобы выполнить инструкцию for/in, интерпретатор JavaScript сначала вычисляет выражение объект. Если оно возвращает значение null или undefined, интерпретатор пропускает цикл и переходит к следующей инструкции. Если выражение возвращает простое значение, оно преобразуется в эквивалентный объект-обертку. В противном случае выражение возвращает объект. Затем интерпретатор выполняет по одной итерации цикла для каждого перечислимого свойства объекта. Перед каждой итерацией интерпретатор вычисляет значение выражения, сохраняет его в переменной и присваивает ему имя свойства (строковое значение).
Обратите внимание, что переменная в цикле for/in может быть любым выражением, возвращающим значение, которое можно использовать слева от оператора присваивания. Это выражение вычисляется в каждой итерации цикла, т.е. каждый раз оно может возвращать разные значения. Например, чтобы скопировать имена всех свойств объекта в массив, можно использовать следующий цикл:
var obj = ; var arr = [], i = 0; for (arr[i++] in obj); // пустое тело цикла console.log(arr); // ["name", "password"]
В действительности цикл for/in может совершать обход не по всем свойствам объекта, а только по перечислимым свойствам. Многочисленные встроенные методы, определяемые в базовом языке JavaScript, не являются перечислимыми. Например, все объекты имеют метод toString(), но цикл for/in не перечислит свойство toString. Кроме встроенных методов также не являются перечислимыми многие другие свойства встроенных объектов. При этом все свойства и методы, определяемые пользователем, являются перечислимыми. Унаследованные свойства, которые были определены пользователем, также перечисляются циклом for/in.
Если в теле цикла for/in удалить свойство, которое еще не было перечислено, это свойство перечислено не будет. Если в теле цикла создать новые свойства, то обычно такие свойстве не будут перечислены. (Однако некоторые реализации могут перечислять унаследованные свойства, добавленные в ходе выполнения цикла.)
Операторы циклов for, while, do while
Ни одна сколь-нибудь серьезная программа на JavaScript не обходится без циклов. Что такое циклы? Представьте, что вам необходимо вычислить вот такую вот сумму:
Расписывать все это через тысячу слагаемых не очень то удобно. И к тому же число слагаемых может зависеть от значения переменной и быть неопределенным. В таких задачах без циклов не обойтись. Представим сначала эту задачу в виде вот такой блок-схемы.
Оператор цикла while
Эта блок схема показывает принцип работы цикла и отсюда хорошо видно, что цикл состоит из двух составляющих: условия цикла и тела цикла, то есть, операторов, которые выполняются внутри цикла. В частности, такую конструкцию можно реализовать с помощью оператора цикла while, по следующему синтаксису:
И программа будет выглядеть так:
let S=0, i=1; while(i 1000) { S += 1/i; ++i; } console.log(S);
В качестве выражения в цикле while можно писать все те же самые условия, что и в условном операторе if. Например, можно вычислять сумму S пока либо i
while(i 1000 && S 5)
Рассмотрим еще один пример. Будем вычислять сумму
и запишем все вот в такой краткой форме:
let S=0, i=1; while((S += i++) 100 ); console.log(S);
Здесь сумма вычисляется непосредственно внутри выражения, а тело цикла отсутствует – после while стоит точка с запятой. Так тоже можно делать, но не рекомендуется, т.к. это усложняет понимание работы программы другими программистами. Лучше все расписывать в несколько строк.
Оператор цикла for
Самый часто используемый оператор цикла – это оператор for, который имеет такой синтаксис:
Давайте перепишем нашу программу подсчета суммы
с помощью цикла for, получим:
let S=0; for(let i=1;i 1000; ++i) S += 1/i; console.log(S);
Здесь весь цикл записан буквально в одну строчку, а тело цикла состоит из одного оператора – подсчета суммы ряда. Именно поэтому здесь не стоят фигурные скобки – для одного оператора они не обязательны.
Вначале идет инициализация счетчика let i=1, через точку с запятой – условие цикла и далее через точку с запятой правило изменения счетчика: увеличение на 1 на каждой итерации. Такая запись цикла выглядит гораздо короче и нагляднее, поэтому оператор for так часто используется на практике.
Вторым примером рассмотрим задачу вычисления значений линейной функции
Скрипт будет выглядеть так:
let f, k = 0.5, b = 2; for(let x=0;x 1; x += 0.1) { f = k*x+b; console.log(f); }
Здесь все достаточно очевидно, только теперь счетчик x у нас меняется от 0 до 1 с шагом 0,1. Далее идет тело цикла из двух операторов, поэтому они заключены в фигурные скобки.
Цикл for можно записывать и в таком виде:
let x=0; for(;x 1; x += 0.1) { . }
let x=0; for(;x 1; ) { f = k*x+b; console.log(f); x += 0.1; }
let x=0; for(;;) { if(x > 1) break; f = k*x+b; console.log(f); x += 0.1; }
В последнем случае мы не прописали никакого условия, поэтому цикл for работал бы вечно. Поэтому в теле цикла добавлена проверка: если x>1, то выполняется оператор break, который прерывает работу цикла. Забегая вперед, скажу, что оператор break прерывает работу любого цикла, не только for.
Оператор цикла do while
Последний оператор цикла, который мы рассмотрим – это цикл do while. Он имеет следующий синтаксис:
Отличие этого цикла от двух предыдущих в том, что он сначала выполняет тело цикла и только потом проверяет условие цикла: если оно истинно, то цикл продолжается, если ложно, то завершается.
Когда может использоваться такая конструкция? Например, если пользователь вводит с клавиатуры некий пароль и мы должны проверить: правильно ли он был введен. Если правильно, то цикл завершается, иначе просим пользователя ввести пароль повторно. Такую программу можно реализовать так:
const PSW = "password"; let psw = null; do { psw = prompt("Введите пароль", ""); } while(psw != PSW); console.log("Вы вошли в систему!");
Вложенные циклы
Итак, мы с вами рассмотрели три цикла: while, for и do while. Все эти циклы можно комбинировать друг с другом. То есть, создавать вложенные циклы. Когда это необходимо? Например, для подсчета вот такой двойной суммы ряда
Программа для ее вычисления будет выглядеть так:
let S=0, M=10, N=5; for(let i=1;i N; ++i) for(let j=1; j M; ++j) S += i*j; console.log("S = " + S);
Мы здесь сначала пробегаем все значения j от 1 до M при фиксированном i=1, затем, значение i увеличивается на 1, становится 2 и при этом i снова пробегаются значения j от 1 до M. И так пока i не превысит значение N. То есть, второй цикл вложен вот в этот первый. И таких вложений можно делать сколько угодно.
Операторы break и continue
Всеми тремя циклами можно управлять с помощью двух специальных операторов: break и continue. Об операторе break мы уже говорили – он прерывает работу любого цикла. Но только одного. Например, здесь при вложенных циклах:
for(let i=1;i N; ++i) for(let j=1; j M; ++j) { if(j == 5) break; S += i*j; }
будет остановлен только один внутренний цикл и управление будет передано внешнему циклу. Чтобы прервать оба цикла можно использовать оператор break с меткой вот так:
all: for(let i=1;i N; ++i) for(let j=1; j M; ++j) { if(j == 5) break all; S += i*j; }
Мы здесь явно указываем внешний цикл с меткой all, который следует прервать. В результате будут остановлены оба цикла. Здесь следует иметь в виду, что в данном случае метки применяются именно к операторам циклов. Если метку записать выше или ниже, она либо не сработает, либо применится к ближайшему циклу, содержащему оператор break.
Следующий оператор continue позволяет пропускать тело цикла и перейти к следующей итерации, не прерывая работу самого цикла. Например, мы хотим перебрать все целые значения от -5 до 5, исключая значение 0. Такую программу можно реализовать так:
for(let i=-5;i 5; ++i) { if(i == 0) continue; console.log("i = " + i); }
При выполнении этой программы увидим, что в консоль выведены все значения кроме нуля. Так как при i=0 срабатывает условие и выполняется оператор continue. Все что находится после этого оператора пропускается и цикл продолжается уже со значением i=1.
Оператор continue также можно использовать с меткой, подобно оператору break.
Вот мы с вами рассмотрели базовые реализации операторов циклов. Забегая вперед, скажу, что в JavaScript имеются и другие реализации для циклов, но о них речь пойдет когда возникнет необходимость в их применении.
Видео по теме
JavaScipt #1: что это такое, с чего начать, как внедрять и запускать
JavaScipt #2: способы объявления переменных и констант в стандарте ES6+
JavaScript #3: примитивные типы number, string, Infinity, NaN, boolean, null, undefined, Symbol
JavaScript #4: приведение типов, оператор присваивания, функции alert, prompt, confirm
JavaScript #5: арифметические операции: +, -, *, /, **, %, ++, --
JavaScript #6: условные операторы if и switch, сравнение строк, строгое сравнение
JavaScript #7: операторы циклов for, while, do while, операторы break и continue
JavaScript #8: объявление функций по Function Declaration, аргументы по умолчанию
JavaScript #9: функции по Function Expression, анонимные функции, callback-функции
JavaScript #10: анонимные и стрелочные функции, функциональное выражение
JavaScript #11: объекты, цикл for in
JavaScript #12: методы объектов, ключевое слово this
JavaScript #13: клонирование объектов, функции конструкторы
JavaScript #14: массивы (array), методы push, pop, shift, unshift, многомерные массивы
JavaScript #15: методы массивов: splice, slice, indexOf, find, filter, forEach, sort, split, join
JavaScript #16: числовые методы toString, floor, ceil, round, random, parseInt и другие
JavaScript #17: методы строк - length, toLowerCase, indexOf, includes, startsWith, slice, substring
JavaScript #18: коллекции Map и Set
JavaScript #19: деструктурирующее присваивание
JavaScript #20: рекурсивные функции, остаточные аргументы, оператор расширения
JavaScript #21: замыкания, лексическое окружение, вложенные функции
JavaScript #22: свойства name, length и методы call, apply, bind функций
JavaScript #23: создание функций (new Function), функции setTimeout, setInterval и clearInterval
© 2024 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
#8 – Циклы в JavaScript. Операторы циклов
За счет циклов вы можете создавать код, что будет циклично выполнен определенное количество раз. Мы в уроке рассмотрим создание циклов в языке JavaScript. Мы изучим циклы: for, while и do while. Дополнительно нами будут изучены операторы для циклов.
Видеоурок
В языке JavaScript, как и в большинстве других языков, существует 3 основных вида циклов. Каждый из них выполняет одну и ту же роль, но записывается по-разному. Рассмотрим все три цикла.
Цикл For
В цикле for все условия записываются в одном месте, что очень удобно во многих случаях. Стандартная запись такого цикла выглядит следующим образом:
for (var i = 0; i < 10; i++) console.log(i);
В объявлении цикла записывается следующее: переменная цикла, её начальное значение и диапазон. В примере выше будут выведены числа от 0 до 10.
Если в теле цикла всего одна строка кода, то фигурные скобки можно пропустить и не записывать их.
Цикл While
Суть цикла while не особо отличается от цикла for . Единственное отличие заключается в способе записи цикла. В while необходимо прописать лишь условие, а все остальные параметры записываются вне цикла:
var i = 1; // Создание переменной while (i
Цикл Do While
Цикл схож с циклом while по форме написания, но при этом работает немного по-другому. Цикл do..while будет выполнен один раз сто процентов, а дальше проверит условие и если оно верно, то цикл будет выполняться дальше:
var x = 13; do < x--; console.log(x); >while (x > 10);
Как видно из примера, цикл изначально неверный, но это не мешает ему сработать один раз.
Операторы для работы в циклах
Существует три основных оператора для работы в циклах:
- Оператор break - служит для выхода из цикла полностью;
- Оператор continue - пропускает лишь одну итерацию и не выходит из цикла.
Весь код будет доступен после подписки на проект!
JavaScript Цикл For
Циклы удобны, если вы хотите запускать один и тот же код снова и снова, каждый раз с другим значением.
Часто это бывает при работе с массивами:
Вместо того чтобы писать:
text += cars[0] + "
";
text += cars[1] + "
";
text += cars[2] + "
";
text += cars[3] + "
";
text += cars[4] + "
";
text += cars[5] + "
";
Вы можете написать проще:
var i;
for (i = 0; i < cars.length; i++) <
text += cars[i] + "
";
>
Различные виды циклов
JavaScript поддерживает разные циклы:
- for - перебирает через блок кода несколько раз
- for/in - перебирает свойства объекта
- for/of - перебирает значения итеративного объекта
- while - перебирает блок кода, пока выполняется указанное условие
- do/while - также перебирает блок кода, пока выполняется указанное условие
Цикл for
Цикл for имеет следующий синтаксис:
for (statement 1; statement 2; statement 3) // блок кода, который нужно выполнить
>
Оператор 1 выполняется (один раз) перед выполнением блока кода
Оператор 2 определяет условие выполнения блока кода.
Оператор 3 выполняется (каждый раз) после выполнения блока кода.
Пример
for (i = 0; i < 5; i++) <
text += "Число является " + i + "
";
>
Из приведенного выше примера вы можете прочитать:
Оператор 1 устанавливает переменную перед началом цикла (var i = 0).
Оператор 2 определяет условие запуска цикла я должен быть меньше 5 (i < 5).
Оператор 3 увеличивает значение (i++) каждый раз, когда выполняется блок кода в цикле.
Оператор 1
Обычно вы используете оператор 1 для инициализации переменной, используемой в цикле (i = 0).
Это не всегда так, JavaScript не волнует. Оператор 1 не является обязательным.
Вы можете инициировать множество значений в оператор 1 (разделенных запятыми):
Пример
for (i = 0, len = cars.length, text = ""; i < len; i++) <
text += cars[i] + "
";
>
И вы можете пропустить оператор 1 (например, когда ваши значения установлены до начала цикла):
Пример
var i = 2;
var len = cars.length;
var text = "";
for (; i < len; i++) <
text += cars[i] + "
";
>
Оператор 2
Часто оператор 2 используется для оценки состояния исходной переменной.
Это не всегда так, JavaScript не волнует. Оператор 2 также необязателен.
Если оператор 2 вернет true, цикл начнется заново, если он вернет false, цикл завершится.
Если вы пропустите оператор 2, вы должны указать break (прерывание) внутри цикла. В противном случае цикл будет постоянно повторяттся и никогда не закончится. Это приведёт к зависанию браузера. Читайте о прерываниях в следующих главах этого руководства.
Оператор 3
Часто оператор 3 увеличивает значение начальной переменной.
Это не всегда так, JavaScript все равно, и оператор 3 необязателен.
Оператор 3 может делать что угодно, например отрицательное приращение (i--), положительное приращение (i = i + 15) или что-то еще.
Оператор 3 также можно пропустить (например, когда вы увеличиваете значения внутри цикла):
Пример
var i = 0;
var len = cars.length;
for (; i < len; ) <
text += cars[i] + "
";
i++;
>
Цикл for/in
JavaScript оператор for/in перебирает свойства объекта:
Пример
var text = "";
var x;
for (x in person) text += person[x];
>
Цикл for/of
JavaScript оператор for/of перебирает значения итерируемых объектов.
Цикл for/of позволяет перебирать итерируемые структуры данных, такие как массивы, строки, карты, списки узлов Node и т.д.
Цикл for/of имеет следующий синтаксис:
for (variable of iterable) // блок кода будет выполняться
>
variable - Для каждой итерации переменной присваивается значение следующего свойства. Переменная может быть объявлена с const , let , или var .
iterable - Объект, имеющий итерируемые свойства.
Цикл массива
Пример
var cars = ["БМВ", "Вольво", "Мини"];
var x;
for (x of cars) document.write(x + "
");
>
Цикл строк
Пример
var txt = "JavaScript";
var x;
Цикл while (в то время, как)
Цикл while и do/while будет объяснен в следующей главе.