Home

Конструкции: ветвления и циклы

Содержание

1. Вступление

Лишь немногие из программ выполняются последовательно от первого оператора к последнему. Как и большинство людей, программы определяют порядок своих действий в зависимости от меняющихся обстоятельств. В программе предусмотрены переходы из одной части программы в другую в зависимости от выполнения или невыполнения некоторого условия. Инструкции, реализующие подобные переходы(поведение) делятся на две основные категории: циклы и ветвления.

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

2. Операции отношения

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

Результатом сравнения является значение истина или ложь. Например, две величины могут быть равны (истина) или не равны (ложь).

Пример

'use strict';
var a = prompt('Введите значение a: ', '');
console.log('a < 10 -', a < 10);
console.log('a > 10 -', a > 10);
console.log('a = 10 -', a == 10);
console.log('a ≠ 10 -', a != 10);

Первое выражение истинно в том случае, если значение a меньше, чем 10; второе — тогда, когда a больше, чем 10; третье — когда a равно 10. и наконец a не равно 10. Как можно видеть из результата работы программы, интерпретатор JavaScript возвращает на место операции отношения значение true или false.

2.1 Сравнение разных типов

При сравнении значений разных типов, используется числовое преобразование за правилами преобразование типов. Оно применяется к обоим значениям.

Пример

'use strict';
alert( '2' > 1 ); // true, сравнивается как 2 > 1
alert( '01' == 1 ); // true, сравнивается как 1 == 1
alert( false == 0 ); // true, false становится числом 0
alert( true == 1 ); // true, так как true становится числом 1.

2.2 Строгое равенство

В обычном операторе == есть «проблема» – он не может отличить 0 от false:

'use strict';
alert( 0 == false );  // true

Та же ситуация с пустой строкой:

'use strict';
alert( ''  == false ); // true

Это естественное следствие того, что операнды разных типов преобразовались к числу. Пустая строка, как и false, при преобразовании к числу дают 0.

Что же делать, если всё же нужно отличить 0 от false?

Для проверки равенства без преобразования типов используются операторы строгого равенства === (тройное равно) и !==.

Если тип разный, то они всегда возвращают false:

'use strict';
alert( 0 === false ); // false, т.к. типы различны

Строгое сравнение предпочтительно, если мы хотим быть уверены, что «сюрпризов» не будет.

2.3* Сравнение с null и undefined

Проблемы со специальными значениями возможны, когда к переменной применяется операция сравнения > < <= >=, а у неё может быть как численное значение, так и null/undefined.

Интуитивно кажется, что null/undefined эквивалентны нулю, но это не так.

Они ведут себя по-другому.
1. Значения null и undefined равны == друг другу и не равны чему бы то ни было ещё. Это жёсткое правило буквально прописано в спецификации языка.
2. При преобразовании в число null становится 0, а undefined становится NaN.

Посмотрим забавные следствия.

2.3.1 Некорректный результат сравнения null с 0

Сравним null с нулём:

'use strict';
alert( null > 0 ); // false
alert( null == 0 ); // false

И так, мы получили, что null не больше и не равен нулю. А теперь…

'use strict';
alert( null >= 0 ); // true

Как такое возможно? Если нечто «больше или равно нулю», то резонно полагать, что оно либо больше, либо равно. Но здесь это не так.

Дело в том, что алгоритмы проверки равенства == и сравнения >= > < <= работают по-разному.

Сравнение честно приводит к числу, получается ноль. А при проверке равенства значения null и undefined обрабатываются особым образом: они равны друг другу, но не равны чему-то ещё.

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

2.3.2 Несравнимый undefined

Значение undefined вообще нельзя сравнивать:

'use strict';
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

- Сравнения (1) и (2) дают false потому, что undefined при преобразовании к числу даёт NaN. А значение NaN по стандарту устроено так, что сравнения ==, <, >, <=, >= и даже === с ним возвращают false.
- Проверка равенства (3) даёт false, потому что в стандарте явно прописано, что undefined равно лишь null и ничему другому.

Вывод: любые сравнения с undefined/null, кроме точного ===, следует делать с осторожностью.

Желательно не использовать сравнения >= > < <= с ними, во избежание ошибок в коде.

3. Ветвления

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

В JavaScript существует несколько типов ветвлений, наиболее важным из которых является if...else, осуществляющее выбор между двумя альтернативами. В инструкции ветвления if...else использование else не является обязательным. Для выбора одной из множества альтернатив используется инструкция ветвления switch(switch Statement), действие которого определяется набором значений соответствующей переменной. Кроме того, существует так называемая условная операция, используемая в некоторых особых ситуациях. Мы рассмотрим каждую из этих конструкций.

3.1 The if Statement/Инструкция if

3.3.1 Оператор if

Оператор if является наиболее простым из операторов ветвлений. Следующие примеры иллюстрируют применение оператора if.

Пример

'use strict';
var a = prompt('Введите значение a: ', '');
if ( a > 100 )
    alert('Это число больше, чем 100');

За ключевым словом if следует условие ветвления, заключенное в круглые скобки. Оператор if (...) вычисляет и преобразует выражение в скобках к логическому типу.

Пример

'use strict';
var year = prompt('В каком году появилась спецификация ECMA-262 5.1?', '');
if (year != 2011)
    alert( 'А вот и неправильно!' );

Оператор if («если») получает условие, в примере выше это year != 2011. Он вычисляет его, и если результат – true, то выполняет команду.

3.3.2 Несколько операторов в теле if

Если нужно выполнить более одной команды – они оформляются блоком кода в фигурных скобках:

Пример

'use strict';
if (year != 2011) {
    alert( 'А вот..' );
    alert( '..и неправильно!' );
}

Пример

'use strict';
var x = prompt('Введите число: ', '');
if (x > 100) {
    alert('Число ', x);
    alert('больше, чем 100');
}

Рекомендуется использовать фигурные скобки всегда, даже когда команда одна.

Это улучшает читаемость кода.

Синтаксис оператора if показан на рисунке:

example img

3.3.3 Оператор if...else

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


Пример

'use strict';
var a = prompt('Введите число: ', '');
if (a > 100)
    alert('Это число больше, чем 100');
else
    alert('Это число не больше, чем 100');

Пример

'use strict';
var year = prompt('Введите год появления стандарта ECMA-262 5.1', '');
if (year == 2011) {
    alert( 'Да вы знаток!' );
} else {
    alert( 'А вот и неправильно!' ); // любое значение, кроме 2011
}

В зависимости от истинности или ложности условия ветвления, программа выводит соответствующее сообщение.

3.3.4 Вложенные ветвления if...else

Возможно, вам приходилось видеть приключенческие игры, предназначенные для ранних версий MS DOS. Их суть заключалась в следующем: играющий двигал своего «героя» по воображаемому ландшафту и замкам среди волшебников, сокровищ и т. д., с помощью текстовых символов. Следующии пример, напоминает небольшую часть такой приключенческой игры.

Пример

'use strict';
var x = 10, y = 10, position = '';
alert('Введите \'end\' для выхода...');
if (position != 'end') {
    alert('Ваши координаты: ' + x + ',' + y);
    position = prompt('Выберите направление (n, s, e, w): ', '');
    if (position == 'n') // движение на север
        y--;
    else
        if (position == 's') // движение на юг
            y++;
        else
            if (position == 'e') // движение на восток
                x++;
            else
                if (position == 'w') // движение на запад
            		x--;
alert('Ваши координаты: ' + x + ',' + y);
}

Когда игра начинается, вы оказываетесь на бесплодном участке земли. Вы можете передвигаться на север, юг, запад и восток, а программа будет следить за вашими передвижениями и сообщать ваши текущие координаты. Начало дви­жения находится в точке с координатами (10, 10). С вашим героем не будет происходить ничего интересного, куда бы он ни пошел; пустая земля простира­ется во всех направлениях, как видно на рисунке:

Для выхода из программы нужно ввести слово ‘end’.

Данная програма не являеться шедевром среди видеоигр, однако в ней демонстрируется применение вложенных ветвлений. Так, оператор if находится внутри оператора if...else, который, в свою очередь, также является частью ветвления if...else. Если первое условие не выполняется, то проверяется второе условие и т. д. до тех пор, пока не будут проверены все условия. Если какое-либо из условий выполняется, то изменяется соответствующая координата x или у, после чего программа выходит из всех вложенных ветвлений. Подобные вложенные группы ветвлений называются деревом ветвлений.

3.3.5 Конструкция else...if

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

Пример

'use strict';
var x = 10, y = 10, position = '';
alert('Введите \'end\' для выхода...');
if (position != 'end') {
    alert('Ваши координаты: ' + x + ',' + y);
    position = prompt('Выберите направление (n, s, e, w): ', '');
    if (position == 'n') { // движение на север
        y--;
        console.log('go north');
    } else {
        if (position == 's') { // движение на юг
            y++;
            console.log('go south');
        } else {
            if (position == 'e') { // движение на восток
         		x++;
                console.log('go east');
            } else {
                if (position == 'w') {  // движение на запад
                    x--;
                    console.log('go west');
                }
            }
        }
    }
alert('Ваши координаты: ' + x + ',' + y);
}   

Существует еще один вариант записи этих же действий. Необходимо только немного изменить последовательность записи кода программы. В результате получим следующий пример:

Пример

'use strict';
var x = 10, y = 10, position = '';
alert('Введите \'end\' для выхода...');
if (position != 'end') {
    alert('Ваши координаты: ' + x + ',' + y);
    position = prompt('Выберите направление (n, s, e, w): ', '');
    if (position == 'n') { // движение на север
        y--;
        console.log('go north');
    } else if (position == 's') { // движение на юг
            y++;
            console.log('go south');
        } else if (position == 'e') { // движение на восток
         		x++;
                console.log('go east');
            } else if (position == 'w') {  // движение на запад
                    x--;
                    console.log('go west');
                }           		   
}
alert('Ваши координаты: ' + x + ',' + y);

У вас может создаться впечатление, что мы использовали новый вид ветвления else...if. Программа последовательно исполняет блоки else...if до тех пор, пока не выполнится хотя бы одно из проверяемых условий. Затем исполняется соответствующий оператор и производится выход из ветвлений. Такой способ представления вложенных ветвлений гораздо проще и удобнее для понимания, чем обычная последовательность конструкций if...else.

3.3.6 Условная операция, тернарный оператор(Conditional Operator)

В этом разделе пойдет разговор об операции, выполняющей несколько нетипичные действия. Существует распространенная в программировании ситуация: переменной необходимо присвоить одно значение в случае выполнения некоторого условия и другое значение в случае невыполнения этого условия. В следующем примере переменной min присваивается наименьшее из значений alpha и beta с помощью конструкции if...else:

Пример

'use strict';
var alpha = 1, beta = 2;
if (alpha < beta) {
    min = alpha;
} else {
    min = beta;
}

Подобные действия на практике оказались настолько распространенными, что была специально разработана условная операция, выполняющая эти действия. Эта операция записывается с помощью двух знаков и использует три операнда. Она является единственной операцией в JavaScript, использующей более двух операндов. С помощью условной операции можно записать предыдущий фрагмент следующим образом:

Пример

'use strict';
var alpha = 1, beta = 2;
min = (alpha < beta) ? alpha : beta;

Правая часть оператора представляет собой условное выражение:

'use strict';
(alpha < beta) ? alpha : beta; // условное выражение

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

условие ? значение1 : значение2;

На рисунке показан синтаксис оператора условия:

3.3.7 Несколько условных операторов

Последовательность операторов '?' позволяет вернуть значение в зависимости не от одного условия, а от нескольких.

Пример

'use strict';
var age = prompt('Ваш возраст?', 18);
var message = (age < 3) ? 'Здравствуй, малыш!' :
    (age < 18) ? 'Привет!' :
        (age < 100) ? 'Здравствуйте!' :
            'Какой необычный возраст!';
alert( message );

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

Вопросительный знак проверяет сначала age < 3, если верно – возвращает 'Здравствуй, малыш!', если нет – идет за двоеточие и проверяет age < 18. Если это верно – возвращает 'Привет!', иначе проверка age < 100 и 'Здравствуйте! И наконец, если ничего из этого не верно, то 'Какой необычный возраст!'.

То же самое через if..else:

Пример

'use strict';
var age = prompt('Ваш возраст?', 18);
if (age < 3) {
    message = 'Здравствуй, малыш!';
} else if (age < 18) {
    message = 'Привет!';
} else if (age < 100) {
    message = 'Здравствуйте!';
} else {
    message = 'Какой необычный возраст!';
}
alert( message );

3.2 The switch Statement/Инструкция switch

3.2.1 Оператор switch..case..default

Если в вашей программе присутствует большое дерево ветвлений и все ветвления зависят от значения какой-либо одной переменной, то можно вместо ступенчатой последовательности конструкций if...else или else...if воспользоваться инструкцией switch. Рассмотрим простой пример:

Пример

'use strict';
var month = +prompt('Введите месяц в формате 1, 2...12', '1');
switch (month) { 
    case 1:
        alert('Январь');
        break;
    case 2:
        alert('Февраль ');
        break;
    case 3:
        alert('Март');
        break;
    case 4:
        alert('Апрель');
        break;
    case 5:
        alert('Май');
        break;
    case 6:
        alert('Июнь');
        break;
    case 7:
        alert('Июль');
        break;
    case 8:
        alert('Август');
        break;
    case 9:
        alert('Сентябрь');
        break;
    case 10:
        alert('Октябрь');
        break;
    case 11:
        alert('Ноябрь');
        break;
    case 12:
        alert('Декабрь');
        break;
}

Различные места в блоке помечены ключевым словом case, за которым следует выражение и символ двоеточия. Ключевое слово case напоминает инструкцию с меткой за исключением того, что оно связывает инструкцию с выражением, а не с именем. Когда выполняется инструкция switch, она вычисляет значение вы­ра­же­ния, а затем ищет метку case, соответствующую этому значению (соответствие определяется с помощью оператора идентичности ===). Если метка найдена, выполняется блок кода следующей за меткой case. Если метка case с соответствующим значением не найдена, выполнение начинается с первой инструкции, следующей за специальной меткой default:. Если метка default: отсутствует, блок инструкции switch пропускается целиком.

Обратите внимание на ключевое слово break в конце каждого блока case. Инструкция break, описываемая далее в следующий главе, приводит к передаче управления в конец инструкции switch и продолжению выполнения инструкций, следующих далее. Конструкции case в инструкции switch задают только начальную точку выполняемого программного кода, но не задают никаких конечных точек. В случае отсутствия инструкций break инструкция switch начнет выполнение блока кода с меткой case, соответствующей значению вы­ра­же­ния, и продолжит выполнение инструкций до тех пор, пока не дойдет до конца блока. В редких случаях это полезно.

Пример

'use strict';
var month = +prompt('Введите месяц в формате 1, 2...12', '1');
switch (month) { 
    case 1:
        alert('Январь');
        break;
    case 2:
        alert('Февраль ');
        break;
    case 12:
        alert('Декабрь');
        break;
    default:
        alert(month + ' - это не зимний месяц');
}

3.2.2 Группировка case

Несколько значений case можно группировать:

Пример

'use strict';
var month = +prompt('Введите месяц в формате 1, 2...12', '1');
switch (month) {
    case 12: 
    case 1:
    case 2:
        alert('Зимний месяц');
        break;
    case 3:
    case 4:
    case 5:
        alert('Весенний месяц');
        break;
    case 6:
    case 7:
    case 8:
        alert('Летний месяц');
        break;
    case 9:
    case 10:
    case 11:
        alert('Осенний месяц');
        break;
}

3.3 Сравнение switch и if ... else

Когда лучше использовать последовательность if...else (или else...if), а когда — switch? При использовании else...if можно проверять значения разных не связанных друг с другом переменных, причем сравнения могут быть любой степени сложности:

Пример

'use strict';
if (SteamPressure * Factor > 56)
   // statement
else if (Voltageln + VoltageOut < 23000)
   // statement
else if (day == Thursday)
   // statement
else
   // statement

В операторе switch все ветвления используют одну и ту же переменную(выражение) единственная возможность проверки в таком ветвлении — сравнение значения переменной с заданной константой. Если хорошо усвоить эти условия, написание конструкций switch становится простым и доступным для понимания, switch рекомендуется использовать там, где это возможно, особенно в случаях, когда дерево ветвлений содержит много ветвей.

3.1.8* Нетрадиционное использование условных операторов

Иногда оператор вопросительный знак '?' используют как замену if:

'use strict';
var company = prompt('Какая компания создала JavaScript?', '');

(company == 'Netscape') ?
   alert('Да, верно') : alert('Неправильно');

Работает это так: в зависимости от условия, будет выполнена либо первая, либо вторая часть после '?'. Результат выполнения не присваивается в переменную, так что пропадёт (впрочем, alert ничего не возвращает).

Рекомендуется не использовать вопросительный знак таким образом.

Несмотря на то, что с виду такая запись короче if, она является существенно менее читаемой. При чтении кода глаз идёт вертикально и конструкции, занимающие несколько строк, с понятной вложенностью, воспринимаются гораздо легче. Возможно, вы и сами почувствуете, пробежавшись глазами, что синтаксис с if более прост и очевиден чем с оператором '?'.

Смысл условного оператора – вернуть то или иное значение, в зависимости от условия. Пожалуйста, используйте его по назначению, а для выполнения разных веток кода есть if.

4. Объект Math

Объект Math является встроенным объектом, хранящим в своих свойствах и методах различные математические константы и функции.

4.1 Свойства объекта Math

Math.E

Константа e, основание натуральных логарифмов.

Math.E; // 2.718281828459045
Math.LN10

Натуральный логарифм числа 10.

Math.LN10; // 2.302585092994046
Math.LN2

Натуральный логарифм числа 2.

Math.LN2; // 0.6931471805599453
Math.LOG10E

Десятичный логарифм числа e.

Math.LOG10E; // 0.4342944819032518
Math.LOG2E

Логарифм числа e по основанию 2.

Math.LOG2E; // 1.4426950408889634
Math.PI

Константа числа π.

Math.PI; //  3.141592653589793
Math.SQRT1_2

Единица, деленная на корень квадратный из 2.

Math.SQRT1_2; // 0.7071067811865476
Math.SQRT2

Квадратный корень из 2.

Math.SQRT2; // 1.4142135623730951

4.2 Методы объекта Math

Обратите внимание, что тригонометрические функции (sin(), cos(), tan(), asin(), acos(), atan() и atan2()) принимают в параметрах или возвращают углы в радианах. Для преобразования радианов в градусы, умножьте их на величину на (180 / Math.PI);

Обратите внимание, что точность большинства математических функций зависит от реализации. Это означает, что различные браузеры могут дать разные результаты, более того, даже один и тот же движок JavaScript на различных операционных системах или архитектурах может выдать разные результаты.

Math.abs( x )

Возвращает абсолютное значение числа.

Math.acos( x )

Возвращает арккосинус числа.

Math.acosh( x )

Возвращает гиперболический арккосинус числа.

Math.asin( x )

Возвращает арксинус числа.

Math.asinh( x )

Возвращает гиперболический арксинус числа.

Math.atan( x )

Возвращает арктангенс числа.

Math.atanh( x )

Возвращает гиперболический арктангенс числа.

Math.atan2( y, x )

Возвращает арктангенс от частного своих аргументов.

Math.cbrt( x )

Возвращает кубический корень числа.

Math.ceil( x )

Возвращает наименьшее целое число, большее, либо равное указанному числу.

Math.clz32( x )

Возвращает количество ведущих нулей 32-битного целого числа.

Math.cos( x )

Возвращает косинус числа.

Math.cosh( x )

Возвращает гиперболический косинус числа.

Math.exp( x )

Вычисляет степень числа e.

Math.expm1( x )

Возвращает exp(x), из которого вычли единицу.

Math.floor( x )

Возвращает наибольшее целое число, меньшее, либо равное указанному числу.

Math.fround( x )

Округляет до ближайшего целого.

Math.hypot( value1, value2, ...values )

Возвращает квадратный корень из суммы квадратов своих аргументов.

Math.imul( x, y )

Возвращает результат умножения 32-битных целых чисел.

Math.log( x )

Возвращает натуральный логарифм числа.

Math.log1p( x )

Возвращает натуральный логарифм числа 1 + x

Math.log10( x )

Возвращает десятичный логарифм числа.

Math.log2( x )

Возвращает двоичный логарифм числа.

Math.max( value1, value2, ...values )

Возвращает наибольшее число из своих аргументов.

Math.min( value1, value2, ...values )

Возвращает наименьшее число из своих аргументов.

Math.pow( base, exponent )

Вычисляет base в степени exponent.

Math.random( )

Возвращает псевдослучайное число в диапазоне от 0 до 1.

Math.round( x )

Возвращает значение числа, округлённое до ближайшего целого.

Math.sign( x )

Возвращает знак числа, указывающий, является ли число положительным, отрицательным или нулём.

Math.sin( x )

Возвращает синус числа.

Math.sinh( x )

Возвращает гиперболический синус числа.

Math.sqrt( x )

Возвращает положительный квадратный корень числа.

Math.tan( x )

Возвращает тангенс числа.

Math.tanh( x )

Возвращает гиперболический тангенс числа.

Math.trunc( x )

Возвращает целую часть числа, убирая дробные цифры.

5. Циклы(Loops)

Действие циклов заключается в последовательном повторении определенной части вашей программы некоторое количество раз. Повторение продолжается до тех пор, пока выполняется соответствующее условие. Когда значение выражения, задающего условие, становится ложным, выполнение цикла прекращается, а управление передается оператору, следующему непосредственно за циклом.

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

В JavaScript(стандарт ES6) существует 5 типов циклов:
- do...while;
- while;
- for;
- for..in;
- for..of;

Повторение цикла называется итерацией, а инструкции циклов в спецификации называються итерирующими инструкциям(IterationStatement)

Циклы for...in и for...of мы рассмотрим в последующих главах курса.

5.1 The for Statement/Цикл for

Большинство изучающих язык JavaScript считают цикл for самым легким для понимания. Все элементы, контролирующие его выполнение, собраны в одном месте, в то время как в циклах других типов они разбросаны внутри цикла, что зачастую делает логику его работы трудной для понимания.

Цикл for организует выполнение фрагмента программы фиксированное число раз. Как правило (хотя и не всегда), этот тип цикла используется тогда, когда число раз, за которое должно повториться исполнение кода, известно заранее.

В примере ниже, выводятся на экран квадраты целых чисел от 0 до 5:

Пример

'use strict';
var i;
for (i = 0; i <= 5; i++)
    alert(Math.pow(i, 2));

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

(i = 0; i <= 5; i++)

Первое из трех выражений называют инициализирующим, второе — условием проверки, а третье — инкрементирующим, как показано на рисунке ниже:

Эти три выражения, как правило (но не всегда), содержат одну переменную, которую обычно называют счетчиком цикла. В примере выше счетчиком цикла является переменная i. Она определяется до того, как начнет исполняться тело цикла.

Под телом цикла понимается та часть кода, которая периодически исполняется в цикле. В нашем примере тело цикла состоит из единственной инструкции:

alert(Math.pow(i, 2));

Рассмотрим, каким образом три выражения, стоящие в круглых скобках инсиукции for, влияют на работу цикла.

- Инициализирующее выражение вычисляется только один раз — в начале выполнения цикла. Вычисленное значение инициализирует счетчик цикла. В примере выше переменная i получает значение 0.

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

- Инкрементирующее выражение предназначено для изменения значения счетчика цикла. Часто такое изменение сводится к инкрементированию счетчика. Модификация счетчика происходит после того, как тело цикла полностью выполнилось. В нашем примере увеличение i на единицу происходит каждый раз после завершения тела цикла.

5.1.1 Несколько инструкций в теле цикла

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

5.1.2 Варианты цикла for

Инкрементирующий оператор не обязательно должен производить операцию инкрементирования счетчика цикла; вместо инкрементирования может использоваться любая другая операция. В следующем примере под названием FACTOR в операторе цикла используется декрементирование счетчика цикла. Программа запрашивает значение у пользователя, а затем подсчитывает факториал этого числа (факториал числа представляет из себя произведение всех целых положительных чисел, не превышающих данное число. Например, факториал числа 5 равен 1*2*3*4*5 = 120).

Пример FACTOR

'use strict';
var a = prompt('Введите значение a: ', '');
for (var i = a, fact = 1; i > 0; i--) {
    fact *= i;
}
alert(fact);

В этом примере инициализирующий оператор присваивает переменной i значение, вводимое пользователем. Условием продолжения цикла является положительность значения i. Инкрементирующее выражение после каждой итерации уменьшает значение i на единицу.

Определение счетчика цикла внутри оператора цикла for:

В последней программе есть еще одно полезное нововведение: переменная i описана прямо внутри оператора цикла.

Подобная конструкция является типичной для JavaScript, и, как правило, наиболее удобна для работы со счетчиками цикла. Такое определение переменной стоит наиболее близко к месту ее употребления. Переменная, описанная в операторе цикла, видна от точки объявления до конца программы.

Несколько инициализирующих выражений и условий цикла:

Вместо одного инициализирующего выражения в операторе цикла for можно использовать несколько выражений, разделяемых запятыми. Подобным же образом можно использовать более одного инкрементирующего выражения. Лишь условие продолжения цикла всегда должно быть одно, как показано в примере FACTOR.

Любое выражение в for может быть пропущено:

Пример FACTOR 2.0

'use strict';
var a = prompt('Введите значение a: ', '');
var i = a, fact = 1;
for (; i > 0; i--) {
    fact *= i;
}
alert(fact);

Инкрементирующее же выражение может быть внесено в тело цикла:

Пример FACTOR 3.0

'use strict';
var a = prompt('Введите значение a: ', '');
var i = a, fact = 1;
for (; i > 0;) {
    fact *= i;
    i--;
}
alert(fact)

А можно и вообще убрать всё, получив бесконечный цикл.

Пример

'use strict';
for (;;) {
    //statement
}

При этом сами точки с запятой ; обязательно должны присутствовать, иначе будет ошибка синтаксиса.

5.2 The while Statement/Цикл while

Цикл for выполняет последовательность действий определенное количество раз. А как поступить в том случае, если заранее не известно, сколько раз понадобится выполнить цикл? Для этого разработан другой вид цикла — while.

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

Пример

'use strict';
var counter = 0;
var a = 1;
while(a != 0)  // цикл, пока значение counter не равно 0
    a = +prompt('Введите значение a: ', '');

Внешне цикл while напоминает упрощенный вариант цикла for. Он содержит условие для продолжения цикла, но не содержит ни инициализирующих, ни инкрементирующих выражений. Синтаксис цикла while показан на рисунке:

До тех пор пока условие продолжения цикла выполняется, исполнение тела цикла продолжается.

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

5.2.1 Несколько инструкций в теле цикла while

Следующий пример, немного модифицированная версия приключенческой игры, демонстрирует применение нескольких инструкций в теле цикла while.Тут мы используем цикл while для непрерывного путешествия:

Пример

'use strict';
var x = 10, y = 10, position = '';
alert('Введите \'end\' для выхода...');
while (position != 'end') {
    alert('Ваши координаты: ' + x + ',' + y);
    position = prompt('Выберите направление (n, s, e, w): ', '');
    if (position == 'n') { // движение на север
        y--;
        console.log('go north');
    } else if (position == 's') { // движение на юг
        y++;
        console.log('go south');
    } else if (position == 'e') { // движение на восток
        x++;
        console.log('go east');
    } else if (position == 'w') {  // движение на запад
        x--;
        console.log('go west');
    }           		   
}

5.3 The do-while Statement/Цикл do...while

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

Большая часть программы находится в составе тела цикла do. Ключевое слово do обозначает начало цикла. Затем, как и в других циклах, следует тело, обрамленное фигурными скобками. Завершает цикл условие продолжения, описываемое с помощью ключевого слова while. Это условие похоже на условие цикла while, но у него есть два отличия: оно располагается в конце цикла и завершается точкой с запятой (;).

Синтаксис цикла do...while показан на рисунке:



Пример

'use strict';
var balance = 100;
do {
    alert('Ваш баланс ' + balance + '$');
    balance -= prompt('Введите сумму, которую вы хотите снять', '0');
} while (balance > 0);
alert('Вы потратили все');

5.4 Выбор типа цикла

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

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

6. Метки. Инструкции перехода: break, continue

Еще одной категорией инструкций языка JavaScript являются инструкции перехода. Как следует из названия, эти инструкции заставляют интерпретатор JavaScript переходить в другое место в программном коде. Инструкция break заставляет интерпретатор перейти в конец цикла или другой инструкции. Инструкция continue заставляет интерпретатор пропустить оставшуюся часть тела цикла, перейти обратно в начало цикла и приступить к выполнению новой итерации. В языке JavaScript имеется возможность помечать инструкции именами, благодаря чему в инструкциях break и continue можно явно указывать, к какому циклу или к какой другой инструкции они относятся.

Подробнее все эти инструкции перехода описываются в следующих подразделах.

6.1 Метки(LabelledStatement)

Любая инструкция может быть помечена указанным перед ней идентификатором и двоеточием:

label :
    statement

Помечая инструкцию, вы тем самым даете ей имя. Пометить можно любую инструкцию, однако помечать имеет смысл только инструкции, имеющие тело, такие как циклы и условные инструкции. Присвоив имя циклу, его затем можно использовать в инструкциях break и continue, внутри цикла для выхода из него или для перехода в начало цикла, к следующей итерации. Инструкции break и continue являются единственными инструкциями в языке JavaScript, с которыми можно указывать метки – о них подробнее рассказывается далее в этой главе.

В JavaScript нет оператора(инструкции) goto, вы можете использовать только метки с break или continue.

Иден­ти­фи­ка­тор, используемый в качестве метки инструкции, может быть любым допустимым идентификатором JavaScript, кроме зарезервированного слова. Имена меток отделены от имен переменных и функций, поэтому в качестве меток допускается использовать идентификаторы, совпадающие с именами переменных или функций. Метки инструкций определены только внутри инструкций, к которым они применяются (и, конечно же, внутри вложенных в них инструкций). Вложенные инструкции не могут помечаться теми же идентификаторами, что и вмещающие их инструкции, но две независимые инструкции могут помечаться одинаковыми метками. Помеченные инструкции могут помечаться повторно. То есть любая инструкция может иметь множество меток.

Избегайте использования меток. Метки редко используются в коде на JavaScript, так как они делают его сложнее в чтении и понимании. Старайтесь использовать вместо них другие конструкции языка, такие как вызовы функций или выбрасывание ошибок.

6.2 BreakStatement/Инструкция break

Существует 2 способа использовать break: с меткой и без.

6.2.1 Инструкция break без метки

Инструкция break приводит к немедленному выходу из самого внутреннего цикла или инструкции switch.

Синтаксис ее прост:

break;

Поскольку инструкция break приводит к выходу из цикла или инструкции switch, такая форма break допустима только внутри этих инструкций.

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

6.2.2 Инструкция break с меткой

Когда инструкция break используется с меткой, она выполняет переход в конец именованной инструкции. В случае отсутствия инструкции с указанной меткой попытка использовать такую форму инструкции break порождает синтаксическую ошибку. Именованная инструкция не обязана быть циклом или инструкцией switch: инструкция break с меткой может выполнять «выход» из любой вмещающей ее инструкции. Объемлющая инструкция может даже быть простым блоком инструкций, заключенным в фигурные скобки исключительно с целью пометить его.

Между ключевым словом break и именем метки не допускается вставлять символ перевода строки. Дело в том, что интерпретатор JavaScript автоматически вставляет пропущенные точки с запятой: если разбить строку программного кода между ключевым словом break и следующей за ним меткой, интерпретатор предположит, что имелась в виду простая форма этой инструкции без метки, и добавит точку с запятой.

Пример

'use strict';
myLabel: {
    console.log(1);
    break myLabel;
    console.log(2);
}
console.log(3);

Пример

'use strict';
outer: for (var i = 0; i < 3; i++) {
    for (var j = 0; j < 3; j++) {
        var input = prompt('Значение в координатах ' + i + ', ' + j, '');
        // если отмена ввода или пустая строка -
        // завершить оба цикла
        if (!input) break outer; // (*)
    }
}
alert('Готово!');

Инструкция break с меткой на практике необходима, только когда требуется прервать выполнение инструкции, не являющейся ближайшим объемлющим циклом или инструкцией switch.

Наконец, обратите внимание, что инструкция break, с меткой или без нее, не может передавать управление через границы функций. Например, нельзя пометить инструкцию объявления функции и затем использовать эту метку внутри функции.

6.3 ContinueStatement/Инструкция continue

Оператор break производит выход из цикла. Тем не менее, могут возникнуть и такие ситуации, когда необходимо при определенном условии не выходить из цикла, а досрочно возвращаться в его начало. Именно таким эффектом обладает применение оператора continue (строго говоря, continue делает переход на завершающую фигурную скобку цикла, откуда производится обычный переход в начало тела цикла).

Синтаксис инструкции continue столь же прост, как и синтаксис инструкции break:

continue;

Инструкция continue может также использоваться с меткой:

continue label;

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

Инструкция continue, как и break, может применяться во вложенных циклах в форме, включающей метку, и тогда заново запускаемым циклом необязательно будет цикл, непосредственно содержащий инструкцию continue. Кроме того, как и для инструкции break, переводы строк между ключевым словом continue и именем метки не допускаются.

7. Логические операции (Binary Logical Operators)

В JavaScript есть 3 логических операции:
- || (ИЛИ);
- && (И);
- ! (НЕ).

Логические операторы &&, || и ! используются для выполнения операций булевой алгебры и часто применяются в сочетании с операторами отношений для объединения двух выражений отношений в одно более сложное выражение. Эти операторы описываются ниже. Чтобы понять, как они действуют, вам может потребоваться еще раз прочитать о концепции булевых значений.

Логические операторы используются, как правило, с примитивами Boolean (логического) типа. В этом случае результатом работы оператора является значение логического типа. Между тем операторы && и || возвращают значение одного из операнда, потому при использовании в качестве аргументов этих операторов величин, тип которых отличен от Boolean, тип возвращаемого значения может быть отличным от Boolean.

Если значение не логического типа - то в процессе вычислений к нему применяться преобразование к логическому типу.

7.1 Логическое И (&&)

Оператор И выглядит как два амперсанда (&&).

operand && operand;

Условно говоря, оператор && действует на трех уровнях. На самом простом уровне, когда в операции участвуют логические операнды, оператор && выполняет операцию «логическое И» над двумя значениями: он возвращает true тогда и только тогда, когда оба операнда имеют значение true. Если один или оба операнда имеют значение false, оператор возвращает false.

Оператор && часто используется для объединения двух выражений отношений:

'use strict';
x == 0 && y == 0; // true то­гда и толь­ко то­гда, ко­гда x и y рав­ны 0

Выражения отношений всегда возвращают значение true или false, поэтому в подобных ситуациях сам оператор && всегда возвращает true или false. Операторы отношений имеют более высокий приоритет, чем оператор && (и ||), поэтому такие выражения можно записывать без использования скобок.

Но оператор && не требует, чтобы его операнды были логическими значениями.

На втором уровне оператор && действует как логическое И для истинных и ложных значений. Если оба операнда являются истинными, оператор возвращает истинное значение. В противном случае, когда один или оба операнда являются ложными, возвращается ложное значение. В языке JavaScript все выражения и инструкции, использующие логические значения, будут также работать с истинными или ложными значениями, поэтому тот факт, что оператор && не всегда возвращает true или false, на практике не вызывает никаких проблем.

Обратите внимание, что в предыдущем абзаце говорилось, что оператор возвращает «истинное значение» или «ложное значение», но при этом не уточнялось, какое именно значение возвращается. Для этого нам необходимо перейти на третий, заключительный уровень оператора &&. Свою работу оператор начинает с вычисления первого операнда – выражения слева. Если выражение слева возвращает ложное значение, значением всего выражения также должно быть ложное значение, поэтому оператор && просто возвращает значение слева и не вычисляет выражение справа.

В противном случае, если значение слева является истинным, тогда результат всего выражения определяется значением справа. Если значение справа является истинным, значением всего выражения также должно быть истинное значение, а если значение справа является ложным, значением всего выражения должно быть ложное значение. Поэтому, когда значение слева является истинным, оператор && вычисляет и возвращает значение справа:

Пример

'use strict';
// Первый аргумент - true,
// Поэтому возвращается второй аргумент
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// Первый аргумент - false,
// Он и возвращается, а второй аргумент игнорируется
alert( null && 5 ); // null
alert( 0 && "не важно" ); // 0

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

Пример

'use strict';
if (a == b) stop(); // Функ­ция stop() вы­зы­ва­ет­ся, толь­ко ес­ли a == b
(a == b) && stop(); // То же са­мое

В целом следует с осторожностью использовать выражения с побочными эффектами (присваивания, инкременты, декременты или вызовы функций) справа от оператора &&, потому что эти побочные эффекты будут проявляться в зависимости от значения слева.

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

Пример

'use strict';
a1 = true  && true;          // t && t вернёт true
a2 = true  && false;         // t && f вернёт false
a3 = false && true;          // f && t вернёт false
a4 = false && (3 == 4);      // f && f вернёт false
a5 = "Cat" && "Dog";         // t && t вернёт "Dog"
a6 = false && "Cat";         // f && t вернёт false
a7 = "Cat" && false;         // t && f вернёт false

7.2 Логическое ИЛИ (||)

Оператор || выполняет операцию «логическое ИЛИ» над двумя операндами. Если один или оба операнда имеют истинное значение, он возвращает истинное значение. Если оба операнда имеют ложные значения, он возвращает ложное значение.

Хотя оператор || чаще всего применяется просто как оператор «логическое ИЛИ», он, как и оператор &&, ведет себя более сложным образом. Его работа начинается с вычисления первого операнда, выражения слева. Если значение этого операнда является истинным, возвращается истинное значение. В противном случае оператор вычисляет второй операнд, выражение справа, и возвращает значение этого выражения.

Как и при использовании оператора &&, следует избегать правых операндов, имеющих побочные эффекты, если только вы умышленно не хотите воспользоваться тем обстоятельством, что выражение справа может не вычисляться.

Пример

'use strict';
o1 = true  || true;         // t || t вернёт true
o2 = false || true;         // f || t вернёт true
o3 = true  || false;        // t || f вернёт true
o4 = false || (3 == 4);     // f || f вернёт false
o5 = "Cat" || "Dog";        // t || t вернёт "Cat"
o6 = false || "Cat";        // f || t вернёт "Cat"
o7 = "Cat" || false;        // t || f вернёт "Cat"

7.3 Логическое НЕ (!)

Оператор ! является унарным оператором, помещаемым перед одиночным операндом. Он используется для инверсии логического значения своего операнда. Например, если переменная x имеет истинное значение, то выражение !x возвращает значение false. Если x имеет ложное значение, то выражение !x возвращает значение false.

В отличие от операторов && и ||, оператор ! преобразует свой операнд в логическое значение (используя правила преобразование к логическому типу) перед тем, как инвертировать его. Это означает, что оператор ! всегда возвращает true или false. Можно преобразовать любое значение x в его логический эквивалент, дважды применив этот оператор: !!x

Будучи унарным, оператор ! имеет высокий приоритет и тесно связан с операндом. Если вам потребуется инвертировать значение выражения, такого как p && q, необходимо будет использовать круглые скобки: !(p && q).

7.4 Использование логических операторов

Давайте рассмотрим, каким образом логические операции соединяют булевы выражения в JavaScript. В следующем примере, ADVENand, логическая операция используется для усложнения приключенческой игры. Теперь мы закопаем сокровище в точке с координатами (7, 11) и попробуем заставить нашего героя отыскать его.

Пример ADVENand

'use strict';
var x = 10, y = 10, position = '';
alert('Введите \'end\' для выхода...');
while (true) {
    alert('Ваши координаты: ' + x + ',' + y);
    position = prompt('Выберите направление (n, s, e, w): ', '');

    if (position == 'end') break;

    if (position == 'n') { // движение на север
        y--;
        console.log('go north');
    } else if (position == 's') { // движение на юг
        y++;
        console.log('go south');
    } else if (position == 'e') { // движение на восток
        x++;
        console.log('go east');
    } else if (position == 'w') {  // движение на запад
        x--;
        console.log('go west');
    }

    if (x == 7 && y == 11) {
        alert('Вы нашли сокровище');
    }        		   
}

Если игрок попадет в точку, где находится сокровище, программа отреагирует на это.

Введем в нашу приключенческую игру новых персонажей — драконов, которые будут обитать на западных и восточных землях и ограничат свободное передвижение нашего героя. Следующая программа, ADVENor, с помощью операции логического ИЛИ реализует нашу задумку:

Пример ADVENor

'use strict';
var x = 10, y = 10, position = '';
alert('Введите \'end\' для выхода...');
while (true) {
    alert('Ваши координаты: ' + x + ',' + y);
    position = prompt('Выберите направление (n, s, e, w): ', '');

    if (position == 'end') break;

    if (position == 'n') { // движение на север
        y--;
        console.log('go north');
    } else if (position == 's') { // движение на юг
        y++;
        console.log('go south');
    } else if (position == 'e') { // движение на восток
        x++;
        console.log('go east');
    } else if (position == 'w') {  // движение на запад
        x--;
        console.log('go west');
    }

    if (x == 7 && y == 11) {
        alert('Вы нашли сокровище');
    }
    if (x <= 5 ||  x >= 15) {
        alert('Осторожно - драконы!');
    }        	        		   
}

8. Резюме

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

Результатом сравнения является значение истина или ложь. Например, две величины могут быть равны (истина) или не равны (ложь).

В JavaScript существует несколько типов ветвлений, наиболее важным из которых является if...else, осуществляющее выбор между двумя альтернативами. В инструкции ветвления if...else использование else не является обязательным. Для выбора одной из множества альтернатив используется инструкция ветвления switch, действие которого определяется набором значений соответствующей переменной. Кроме того, существует так называемая условная операция, используемая внекоторых особых ситуациях.

Объект Math является встроенным объектом, хранящим в своих свойствах и методах различные математические константы и функции.

Действие циклов заключается в последовательном повторении определенной части вашей программы некоторое количество раз.

В JavaScript существует 5 типов циклов.

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

Инструкция break заставляет интерпретатор перейти в конец цикла или другой инструкции. Инструкция continue заставляет интерпретатор пропустить оставшуюся часть тела цикла, перейти обратно в начало цикла и приступить к выполнению новой итерации.

Логические операторы &&, || и ! используются для выполнения операций булевой алгебры и часто применяются в сочетании с операторами отношений для объединения двух выражений отношений в одно более сложное выражение.

Логические операторы используются, как правило, с примитивами логического типа. В этом случае результатом работы оператора является значение логического типа. Между тем операторы && и || возвращают значение одного из операнда, потому при использовании в качестве аргументов этих операторов величин, тип которых отличен от логического, тип возвращаемого значения может быть отличным от Boolean.

Control flow is really what makes our programs flexy. Variables and constants may contain all the interesting information, but control flow statements allow us to make useful choices based on that data.

9. Упражнения

1. Треугольник в цикле

Напишите цикл, который за 7 вызовов console.log выводит такой треугольник:

#
##
###
####
#####
######
#######

Будет полезно знать, что длину строки можно узнать, приписав к переменной .length.

2. 1..n

Напишите программу, которая выводит через console.log все числа от 1 до 100.

3. FizzBuzz

Напишите программу, которая выводит через console.log все числа от 1 до 100, с двумя исключениями. Для чисел, нацело делящихся на 3, она должна выводить ‘Fizz’, а для чисел, делящихся на 5 (но не на 3) – ‘Buzz’.

Когда сумеете – исправьте её так, чтобы она выводила «FizzBuzz» для всех чисел, которые делятся и на 3, и на 5.

(На самом деле, этот вопрос подходит для собеседований, и, говорят, он позволяет отсеивать довольно большое число кандидатов. Поэтому, когда вы решите эту задачу, можете себя похвалить.)

4. Chess board

Напишите программу, создающую строку, содержащую решётку 8х8, в которой линии разделяются символами новой строки. На каждой позиции либо пробел, либо #. В результате должна получиться шахматная доска.

# # # #
 # # # #
# # # #
 # # # #
# # # #
 # # # #
# # # #
 # # # #

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

5. charSum

Пользователь вводит целое положительное число m (prompt), найти сумму цифр и вывести в консоль.

6. Prime number

Пользователь вводит целое положительное число m (prompt), является ли число m простым? Результат вывести в консоль.

7. Z means Zaporozhye

Выведите в консоль индекс буквы "З" в фразе "Мы приехали в Запорожье".

9. Z means Zaporozhye (sequel)

Выведите в консоль индексы всех букв "З" и "з" в фразе "Мы заехали с Захаром в Запорожье".

10. I don't know about indexOf method yet

Ниже приведен текст. В этом тексте найдите и выведите в консоль индекс всех вхождений таких фрагментов : of, in, new, from, this, rail splitter.

The nationalism of Hamilton was undemocratic. The democracy of Jefferson was,
in the beginning, provincial. The historic mission of uniting nationalism and
democracy was in the course of time given to new leaders from a region beyond
the mountains, peopled by men and women from all sections and free from those
state traditions which ran back to the early days of colonization. The voice
of the democratic nationalism nourished in the West was heard when Clay of
Kentucky advocated his American system of protection for industries; when
Jackson of Tennessee condemned nullification in a ringing proclamation that
has taken its place among the great American state papers; and when Lincoln
of Illinois, in a fateful hour, called upon a bewildered people to meet the
supreme test whether this was a nation destined to survive or to perish. And
it will be remembered that Lincolns party chose for its banner that earlier
device--Republican--which Jefferson had made a sign of power. The "rail splitter"
from Illinois united the nationalism of Hamilton with the democracy of Jefferson,
and his appeal was clothed in the simple language of the people, not in the
sonorous rhetoric which Webster learned in the schools.        

Например фрагмент 'was' встречается 6 раз на таких индексах :
Пример

was -> 28
was -> 28
was -> 73
was -> 166
was -> 441
was -> 792
was -> 1098