Ветвление: if и else

До сих пор все программы в курсе выполнялись одинаково: строка за строкой, сверху вниз, без пропусков. Но реальная программа должна реагировать на данные: показать оценку «зачёт» одному студенту и «пересдача» другому, пустить в зал по билету и остановить без него. Значит, часть кода должна выполняться не всегда, а только при выполненном условии.

Такой код и оформляют через if:

if.jsjs
const score = 75;if (score >= 60) {  console.log('зачёт');}console.log('проверка завершена');
Консоль
зачёт
проверка завершена

В скобках после if стоит условие, в фигурных – блок кода. «Зачёт» напечатался только потому, что score >= 60 истинно. Будь счёт меньше 60 – блок в фигурных скобках был бы пропущен целиком, а программа продолжилась бы со следующей строки: «проверка завершена» печатается в любом случае.

else: когда условие ложно

exam.jsjs
const score = 40;if (score >= 60) {  console.log('зачёт');} else {  console.log('пересдача');}
Консоль
пересдача

else подхватывает противоположный случай: условие ложно – выполняется его блок. Здесь 40 меньше 60, поэтому в консоли «пересдача».

Из двух веток выполняется ровно одна – либо if, либо else; обе сразу не выполняются никогда. По шагам:

if и else: выполняется одна ветка
const score = 40;
В score – число 40.
if (score >= 60) {
console.log('зачёт');
} else {
console.log('пересдача');
}
Консоль
Нет вывода в консоль.

else if: цепочка проверок

Вариантов больше двух – проверки выстраиваются одна за другой.

grades.jsjs
const score = 75;if (score >= 90) {  // 75 меньше 90 – мимо  console.log('отлично');} else if (score >= 60) {  // первая истинная ветка  console.log('зачёт');} else {  // уже не проверяется  console.log('пересдача');}
Консоль
зачёт

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

Поэтому порядок веток – часть логики. Проверки выстраивают от частного к общему: поменяйте первые две проверки местами – и отличник со счётом 95 получит «зачёт». 95 >= 60 истинно, цепочка выполнит эту ветку, а до проверки score >= 90 дело уже не дойдёт.

Цепочка: сверху вниз до первой истины
const score = 75;
В score – число 75.
if (score >= 90) {
console.log('отлично');
} else if (score >= 60) {
console.log('зачёт');
} else {
console.log('пересдача');
}
Консоль
Нет вывода в консоль.

Цепочка или несколько if

Проверки в цепочке можно записать и по отдельности – получится другая программа. Сравним на одном и том же счёте 95, у которого истинны оба условия:

chain.jsjs
const score = 95;if (score >= 90) {  console.log('отлично');} else if (score >= 60) {  console.log('зачёт');}
Консоль
отлично
Цепочка: первая ветка истинна – вторая даже не проверялась.
two-ifs.jsjs
const score = 95;if (score >= 90) {  console.log('отлично');}if (score >= 60) {  console.log('зачёт');}
Консоль
отлично
зачёт
Два независимых if: каждый проверил своё условие – сработали оба.

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

Выбор идёт от смысла задачи. Оценка у работы одна – значит цепочка. А, например, у заказа может быть сразу и скидка за объём, и бесплатная доставка: это независимые условия, и каждое проверяется своим if.

status.jsjs
const orders = 12;if (orders >= 10) {  console.log('золотой статус');} else if (orders >= 3) {  console.log('серебряный статус');}
Консоль
золотой статус
Статус у клиента один – цепочка: 12 заказов проходят обе проверки, но выполнилась только первая ветка.
bonuses.jsjs
const total = 6000;if (total >= 5000) {  console.log('бесплатная доставка');}if (total >= 3000) {  console.log('скидка 5%');}
Консоль
бесплатная доставка
скидка 5%
Бонусы независимы и копятся – отдельные if: заказ на 6000 получил оба.

Условие приводится к булеву

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

Правило приведения короткое. Ложными считаются шесть значений: false, 0, пустая строка '', null, undefined и NaN. Всё остальное – истинно: любое ненулевое число, любая непустая строка (даже '0' и 'false'), любой объект или массив, даже пустые.

truthy.jsjs
const name = 'Ира';// строка непустая – истиннаif (name) {  console.log(`Привет, ${name}!`);}const errors = 0;// ноль ложный, ! перевернулif (!errors) {  console.log('Все проверки пройдены');}
Консоль
Привет, Ира!
Все проверки пройдены

Так if (name) читается «если имя непустое», а if (!errors) – «если ошибок нет». Это сокращает код, но if (count) не выполнится и при нуле, хотя ноль может быть законным значением – например, количеством товара на складе. Там, где ноль – данные, пишите сравнение явно: if (count > 0).

Составные условия

compound.jsjs
const age = 20;const isBlocked = false;if (age >= 18 && !isBlocked) {  // обе проверки прошли  console.log('доступ открыт');}const day = 6;if (day === 6 || day === 7) {  // хватило одной истинной  console.log('выходной');}
Консоль
доступ открыт
выходной

Условие в скобках – обычное выражение: логические операторы соединяют в нём несколько проверок. age >= 18 && !isBlocked – одно условие из двух, и if получает от него готовый ответ.

Фигурные скобки

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

В ветку дописали вторую строку
Со скобками: обе строки в ветке
if (score >= 60) {  console.log('зачёт');  // тоже только при зачёте  console.log('сертификат отправлен');}
Без скобок: вторая строка выпала из ветки
if (score >= 60)  console.log('зачёт');  // выполнится ВСЕГДА, ветка кончилась строкой выше  console.log('сертификат отправлен');
В нижнем варианте отступ обманывает: он выглядит как часть ветки, но для движка ветка закончилась на первой инструкции – сертификат выдадут и двоечнику.

Поэтому договоримся ставить фигурные скобки всегда, даже вокруг одной строки: тогда дописанная строка попадает туда, куда её и клали.

// теперь вы знаете

  1. if выполняет блок только при истинном условии; else подхватывает противоположный случай
  2. Из if и else выполняется ровно одна ветка
  3. Цепочка else if выполняет первую истинную ветку; независимые if могут сработать все
  4. Порядок веток – часть логики: от частных случаев к общим
  5. Условие приводится к boolean: if (name) – «если имя непустое»

Проверьте себя

Что попадёт в консоль при score = 60?

const score = 60;
if (score >= 60) {
console.log('зачёт');
} else {
console.log('пересдача');
}

Верно ли, что у каждого if обязательно должна быть ветка else?

Что напечатает этот код – и что не так с порядком веток?

const age = 70;
if (age >= 18) {
console.log('взрослый билет');
} else if (age >= 60) {
console.log('льготный билет');
}

Что попадёт в консоль?

const temp = 30;
if (temp >= 25) {
console.log('жарко');
}
if (temp >= 15) {
console.log('тепло');
}

Выполнится ли тело if ('0') – и почему?

Скобки не поставили. Что попадёт в консоль при age = 10?

const age = 10;
if (age >= 18)
console.log('доступ открыт');
console.log('добро пожаловать');
переключают уроки · не работают при фокусе в полях ввода