Поток исполнения – это последовательность выполнения инструкций в приложении. Стандартный поток исполнения – последовательное выполнение инструкций по строчке: строка 1 в коде приложения, строка 2 в коде приложения, строка 3 в коде приложения и так далее. Все языки программирования предоставляют инструменты, позволяющие управлять этим потоком, самый базовый инструмент – «if», ветвление. Ниже – о том, зачем это нужно, как именно можно «настраивать» ветвление и когда нужно использовать «старшего брата» оператора if.
«If» переводится как «если», этот оператор применяется тогда, когда нам нужно проверить какое-то условие на истинность, и сделать какое-либо действие только в том случае, если условие – истинное:
let number = 10;
if (number > 0) {
console.log("Число положительное");
}
После ключевого слова «if» мы пишем условие в круглых скобках, если условие окажется истинным – будет исполнен тот блок кода, который помещен в фигурные скобки. Если нам нужно выполнить всего одну инструкцию – фигурные скобки можно опустить, но хорошей практикой считается использование фигурных скобок даже в том случае, если инструкция – одна. Как видите, здесь оператор if меняет поток исполнения: если условие – истинно, то блок кода будет исполнен; если условие – ложно, то блок кода будет пропущен.
В примере выше мы покрыли те случаи, когда число – больше нуля. Но что делать, если нам нужно обработать вообще все случаи? Для этого существует необязательный оператор else, следующий за if:
let number = 10;
if (number > 0) {
console.log("Число положительное");
} else {
console.log("Число отрицательное или равно нулю");
}
Когда мы добавляем else, поток исполнения может пойти в двух направлениях: если условие if будет истинно, то сработает блок кода в его фигурных скобках; если условие if будет ложно, то сработает блок кода, прописанный в else. Таким образом один из блоков кода всегда будет исполнен.
Мы можем добавить в блок if больше условий – для этого существует else if:
let number = 10;
if (number > 0) {
console.log("Число положительное");
} else if (number < 0) {
console.log("Число отрицательное");
} else {
console.log("Число равно нулю");
}
Интерпретатор последовательно проходится по каждому условию сверху вниз, и если одно из условий оказывается положительным, то исполняется связанный с ним блок кода (и только он); если ни одно из условий не является положительным, исполняется тот блок, который прописан в else. Конструкция «if – else if – else» позволяет создавать сложные ветвления – настолько сложные, что иногда в них сложно разобраться:
let score = 85;
if (score >= 90) {
console.log("Отлично");
} else if (score >= 80) {
console.log("Очень хорошо");
} else if (score >= 70) {
console.log("Хорошо");
} else if (score >= 60) {
console.log("Удовлетворительно");
} else if (score >= 50) {
console.log("Проходной балл");
} else if (score >= 40) {
console.log("Ниже среднего");
} else if (score >= 30) {
console.log("Плохо");
} else if (score >= 20) {
console.log("Очень плохо");
} else if (score >= 10) {
console.log("Ужасно");
} else {
console.log("Неудовлетворительно");
}
Этот блок кода выглядит не очень хорошо, а изменять его – вообще сомнительное удовольствие. Если условий становится слишком много, нужно использовать другой оператор ветвления – switch.
Switch проще объяснить на примере:
let fruit = "apple";
switch (fruit) {
case "apple":
console.log("This is an apple.");
// Fallthrough
case "banana":
console.log("This is a banana.");
break;
case "orange":
console.log("This is an orange.");
break;
default:
console.log("Unknown fruit.");
}
Сначала мы пишем ключевое слово «switch», после которого в скобках указываем переменную, которую рассматриваем. Затем мы прописываем блоки case – если переменная равна значению в блоке, будет исполнен код блока case, указанный после «:». Дополнительно мы можем указать блок default – если ни одно из условий case не сработает, будет исполнен default (по аналогии с else).
Switch часто не любят из-за одной встроенной механики, которая называется fallthrough. Дело вот в чем – как только switch находит совпадение с case, он начинает последовательно исполнять все блоки кода, пока не встретит «break». Если в примере выше переменная fruit будет хранить в себе строку “apple” (что и происходит), switch сначала исполнит строку
console.log("This is an apple.");
, после чего «залезет» в следующий case и исполнит строку:
console.log("This is a banana.");
Только после этого switch встретит break и закончит исполнение. Если бы в коде не было ни одного break – исполнились бы все строки кода, даже из default. Иногда fallthrough бывает очень полезен, но чаще просто раздражает – из-за него приходится в каждом блоке case писать отдельный break, что раздувает код.
В JavaScript есть тернарный оператор – оператор, имеющий 3 операнда. Этот оператор – краткая версия if-else:
let age = 18;
let message = (age >= 18) ? "Взрослый" : "Несовершеннолетний";
console.log(message);
Тернарный оператор принято использовать при создании переменной, когда ее значение зависит от условия. В примере выше мы создаем переменную message, которой в качестве значения передаем «Взрослый», если условие в скобках будет истинным, и «Несовершеннолетний», если условие в скобках будет ложным. В теории тернарные операторы можно использовать и как обычный if, а не для создания переменной, но это считается плохой практикой, так как существенно ухудшает читаемость кода.
Тезисно: