Условные операторы if и switch

На этом занятии поговорим об условных операторах. Что это такое? Представьте, что вам нужно вычислить модуль числа, хранящегося в переменной x. Как это сделать? Очевидно, нужно реализовать такой алгоритм.

И в этом алгоритме есть вот такое ветвление программы: при x<0 меняется знак на противоположный, а при других x это не делается. В результате получаем модуль числа в переменной x.

Так вот, чтобы реализовать проверку таких условий в JavaScript имеется два условных оператора: if и switch. И начнем с рассмотрения первого оператора if. В самом простом случае его синтаксис такой:

if(<выражение>) оператор;

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

let x = -5;
if(x < 0) x = -x;
console.log("|x| = " + x);

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

Какие операторы сравнения существуют в JavaScript и как они работают? Многие из них нам известны из школьного курса математики, это:

a > b

Истинно, если a больше b

a < b

Истинно, если a меньше b

a >= b

Истинно, если a больше или равно b

a <= b

Истинно, если a меньше или равно b

a == b

Истинно, если a равно b (обратите внимание, для сравнения используется двойной знак равенства)

a != b

Истинно, если a не равно b

Все эти операторы при сравнении возвращают булевое значение: true – истина или false – ложь. Например:

console.log( 2 > 1 );  // true (верно)
console.log( 2 == 1 ); // false (неверно)
console.log( 2 != 1 ); // true (верно)

Результат сравнения можно присвоить переменной, как и любое значение:

let result = 7 > 5; // результат сравнения присваивается переменной result
console.log( result ); // true

Сравнение строк

Как вы видите, сравнение двух числовых значений выполняется вполне очевидным образом. Но можно ли, например, сравнивать строки между собой? Оказывается да, можно. Чтобы определить, что одна строка больше другой, JavaScript использует «алфавитный» или «лексикографический» порядок. Другими словами, строки сравниваются посимвольно. Например:

console.log( 'Я' > 'А' ); // true
console.log( 'Кот' > 'Код' ); // true
console.log( 'Сонный' > 'Сон' ); // true

Алгоритм сравнения двух строк довольно прост:

  1. Сначала сравниваются первые символы строк.
  2. Если первый символ первой строки больше (меньше), чем первый символ второй, то первая строка больше (меньше) второй.
  3. Если первые символы равны, то таким же образом сравниваются уже вторые символы строк.

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

В примерах выше сравнение 'Я' > 'А' завершится на первом шаге, тогда как строки "Кот" и "Код" будут сравниваться посимвольно:

  1. К равна К.
  2. о равна о.
  3. т больше чем д.
На этом сравнение заканчивается. Первая строка больше.

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

При сравнении значений разных типов JavaScript приводит каждое из них к числу. Например:

console.log( '2' > 1 ); // true, строка '2' становится числом 2
console.log( '01' == 1 ); // true, строка '01' становится числом 1

При сравнении булевых значений:

console.log( true == 1 ); // true (true приводится к 1)
console.log( false == 0 ); // true (false приводится к 0)
console.log( null == undefined ); // true (обе величины приводятся к 0)

Однако, при использовании сравнения с помощью операторов <, >, <=, >= всюду получим false:

console.log( null >= undefined );  // false (null – к нулю, undefined – к NaN)
console.log( null <= undefined );  // false (null – к нулю, undefined – к NaN)

Внимание! Странное сравнение null с нулем:

console.log( null > 0 );  // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true

Это просто нужно иметь в виду при программировании логики скриптов.

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

В JavaScript можно выполнять сравнение двух значений с учетом их типа данных. Для этого используется оператор === (три равно). Применяя его к предыдущему примеру, получим:

console.log( true === 1 ); //false
console.log( false === 0 ); //false

Оба результата дадут ложь – false, так как значения, имеющие разные типы считаются не равными друг другу. Та же ситуация будет и при таком строгом сравнении:

console.log( "5" === 5 ); //false
console.log( "7" === 7 ); //false
console.log( null === undefined ); // false

Здесь также имеем разные типы данных, поэтому результат – false. А вот если взять строгое неравенство, то получим истину во всех случаях:

console.log( "5" !== 5 ); //true
console.log( null !== undefined ); // true

Вот так можно сравнивать между собой значения с учетом их типов.

Теперь, когда мы знаем как сравниваются между собой величины, вернемся к нашему условному оператору if. И предположим, что хотим определить знак числа в переменной x. Конечно, проверку можно записать вот так:

let x = -5;
if(x < 0) console.log("x отрицательное число");
if(x >= 0) console.log("x неотрицательное число");

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

if(x < 0) console.log("x отрицательное число");
else console.log("x неотрицательное число");

Теперь, у нас здесь всего одно условие. Если оно истинно, то выполнится первый console.log, а иначе – второй console.log. Такая программа будет работать быстрее.

В общем случае, синтаксис оператора if else следующий:

if(<выражение>) оператор 1;
else оператор 2;

И так как после else можно ставить любой оператор, то предыдущую программу можно записать и так:

if(x < 0) console.log("x отрицательное число");
else if(x > 0) console.log("x положительное число");
else console.log("x равен 0");

И вообще таких конструкций if else может быть много. Далее, обратим внимание на такой факт: во всех наших примерах по условию шел один оператор – console.log. Но что если нужно выполнить несколько операторов по некоторому условию? Для этого их нужно заключать в фигурные скобки. Например:

let x = -10, sgn = 0;
if(x < 0) {
         sgn = -1;
         console.log("x отрицательное число", sgn);
}
else if(x > 0) {
         sgn = 1;
         console.log("x положительное число", sgn);
}
else console.log("x равен 0", sgn);

Здесь по первым двум условиям выполняется два оператора: присвоение значения переменной sgn и вывод результата в консоль. В последнем else записан только один оператор – вывод в консоль, поэтому здесь фигурные скобки ставить не обязательно.

В ряде случаев конструкцию if else удобнее записывать через тернарный условный оператор, который имеет такой синтаксис:

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

Сначала вычисляется условие: если оно истинно, то возвращается значение1, в противном случае – значение2. Например:

let accessAllowed = (age > 18) ? true : false;

Получим true, если возраст (age) больше 18, иначе – false. Кстати, проверку из данного примера можно сделать короче, просто прописав

let accessAllowed = age > 18;

здесь оператор > вернет true при возрасте больше 18 и false – в противном случае.

Теперь, когда мы разобрались с базовыми моментами проверки условий, сделаем следующий шаг и попробуем реализовать проверку попадания переменной x в диапазон [2; 7], то есть, условие должно быть истинным, когда x принимает значения в этом диапазоне чисел. Очевидно, что здесь должно быть две проверки: первая – мы проверяем, что x >= 2 и вторая – проверяем, что x <= 7. Если оба этих условия выполняются одновременной, то x попадает в наш диапазон.

Реализовать такую проверку на JavaScript можно так:

let x = 4;
if(x >= 2 && x <= 7) console.log("x попадает в [2; 7]");
else console.log("x не попадает в [2; 7]");

Смотрите, здесь записано два условия, объединенных по И (два амперсанда – это И). В результате, общее составное условие будет считаться истинным, если истинно и первое и второе условие. Если хотя бы одно из этих условий ложно, то ложно и все составное условие. В результате мы корректно реализуем проверку на вхождение значения переменной в диапазон [2; 7].

А теперь давайте реализуем противоположное условие, что x не принадлежит диапазону [2; 7]. Условие будет таким:

let x = 40;
if(x < 2 || x > 7) console.log("x не попадает в [2; 7]");
else console.log("x попадает в [2; 7]");

Здесь в составном условии используется связка по ИЛИ (две вертикальные черты – это ИЛИ) и оно будет истинно, если истинно или первое, или второе условие. То есть, в нашем случае, если x < 2 или x > 7, то делается вывод о невхождении переменной x в указанный диапазон.

Итак, запомните следующие правила:

  • условие x >= 2 && x <= 7 истинно, если истинно каждое из подусловий (x>=2 и x <= 7) и ложно, если ложно хотя бы одно из них;
  • условие x < 2 || x > 7 истинно, если истинно хотя бы одно из подусловий (x < 2 или x > 7) и ложно, когда оба ложны.

Вот так можно записывать более сложные условия в условном операторе if. Причем они могут комбинироваться в любом сочетании, например:

let x = 4, y = -2;
if(x >= 2 && x <= 7 && (y < 0 || y > 5)) 
         console.log("x попадает в [2; 7], y не попадает в [0; 5]");

Здесь реализована проверка, что x должно принадлежать [2; 7], а y не принадлежать [0; 5]. И обратите внимание вот на эти круглые скобки. Дело в том, что приоритет у операции && больше, чем у ||, поэтому без скобок у нас бы получилась вот такая проверка:

if( (x >= 2 && x <= 7 && y < 0) || (y > 5) )

то есть, мы проверяли бы, что x принадлежит [2; 7] и y меньше нуля ИЛИ y больше 5. Как вы понимаете – это уже совсем другая проверка. Поэтому учитывайте приоритет этих операций при формировании составного условия. Если нужно изменить приоритет – используйте круглые скобки.

Одиночные проверки

Внутри условия можно прописывать и такие одиночные выражения:

let x = 4, y = true, z = false;
if(x) console.log("x = " + x + " дает true");
if(!0) console.log("0 дает false");
if("0") console.log("строка 0 дает true");
if(!"") console.log("пустая строка дает false");
if(y) console.log("y = true дает true");
if(!z) console.log("z = false дает false");

Вот этот восклицательный знак – это отрицание – НЕ, то есть, чтобы проверить, что 0 – это false мы преобразовываем его в противоположное состояние с помощью оператора отрицания НЕ в true и условие срабатывает. Аналогично и с переменной z, которая равна false.

Из этих примеров можно сделать такие выводы:

  1. Любое число, отличное от нуля, дает true. Число 0 преобразуется в false.
  2. Пустая строка – это false, любая другая строка с символами – это true.
  3. С помощью оператора НЕ можно менять условие на противоположное (в частности, false превращать в true).

Итак, в условиях мы можем использовать три оператора: &&, || и !. Самый высокий приоритет у операции НЕ, следующий приоритет имеет операция И и самый маленький приоритет у операции ИЛИ.

Вот так работает оператор if в JavaScript.

Оператор switch

Второй условный оператор switch используется, когда из множества возможных вариантов нужно выбрать какой-то один. Например, мы хотим проверить: принимает ли некая переменная одно из значений 1, 2, 3 или 4. Это будет выглядеть так:

let item = 3;
switch(item) {
         case 1: console.log("item = 1");
         case 2: console.log("item = 2");
         case 3: console.log("item = 3");
         case 4: console.log("item = 4");
         default: console.log("item другое значение");
}

И в консоле увидим, что item=3, 4 и другое значение. Почему так и как это все работает? В круглых скобках оператора switch записывается переменная, которая сравнивается со значениями (константами), указанными в case. Далее, через двоеточие пишутся операторы, которые выполняются при совпадении значения переменной с константой.  В нашем случае item=3, срабатывает case 3 и выполняется console.log("item = 3"). Но, оператор switch в JavaScript реализован так, что все последующие операторы тоже будут выполняться. В ряде случаев это бывает полезно и нужно. Если же мы хотим прервать выполнение оператора switch после успешной проверки, нужно записать оператор break вот так:

switch(item) {
         case 1: console.log("item = 1");break;
         case 2: console.log("item = 2");break;
         case 3: console.log("item = 3");break;
         case 4: console.log("item = 4");break;
         default: console.log("item другое значение");
}

Теперь в консоле мы видим только строчку item=3. Операторы, стоящие после default выполняются, если не сработала ни одна из проверок. Это необязательное ключевое слово: switch может быть записан и без него, но тогда мы не увидим «item другое значение», если переменная не будет равна 1, 2, 3 или 4.

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

В практике программирования в 99% случаев используется if и лишь для некоторых частных проверок – оператор switch.

Видео по теме