И ifs
, и switches
предназначены для выбора одного из немногих возможных фрагментов кода.
В случае выражения выбранный фрагмент кода оценивается и становится результатом выражения. Когда это оператор, ожидается, что он будет иметь некоторые побочные эффекты, так как код просто запускается.
Некоторые языки, такие как Elm, очень строгие. Когда есть if
, должно быть else
. Когда есть case
(имя вяза для switch
выражения), он должен перечислять все возможные значения. Другие языки, например JavaScript, этого не требуют.
Также бывают случаи, когда switch
быстрее, чем if
.
Признаюсь, я даже не помню, когда написал свои первые ifs
и switches
. Так что еще более неловко сказать, что я обнаружил самое важное различие между этими двумя не так давно. И это совсем не то, о чем я говорил выше.
If
выбирает один фрагмент кода, когда значение true
(или истинное значение), и другой, когда оно false
(или ложное). Всегда есть только два проверяемых значения: true
и false
.
Switch
связывает разные фрагменты кода с разными значениями. Может быть много значений, и они определяются пользователем.
Давайте посмотрим на очень простой пример. Речь идет о загрузке чего-либо по сети. Этот код ifs
побудил меня написать:
if (state.isLoaded) {
// ...
} else {
// ...
if (state.errorOccurred) {
// ...
} else {
// ...
}
// ...
}
Если бы я писал это на TypeScript, было бы очень заманчиво определить тип state
следующим образом:
let state: {isLoaded: boolean, errorOccurred: boolean};
Хотя на первый взгляд это может показаться законным, это не так.
Компилятор никогда не заметит, что следующее состояние некорректно:
state = {isLoaded: true, errorOccurred: true};
Правильный тип выглядит примерно так:
let state:
{isLoaded: true, errorOccurred: false}
| {isLoaded: false, errorOccurred: true}
| {isLoaded: false, errorOccurred: false}
;
Как мы видим, логика нашего приложения действительно заботится не о двух логических значениях, а о трех возможных состояниях.
let state: "loading" | "loaded" | "error";
Как только мы обнаружим все возможные состояния, мы сможем назначить им разные поведения, используя switch
. Больше нет необходимости проверять логические значения.
switch (state) {
case "loading":
// ...
break;
case "error":
// ...
break;
case "loaded":
// ...
break;
}
Как бы мало смысла в этом не было, мы можем согнуть if
, чтобы он выглядел как switch
, и наоборот:
if (state === "loading") { // ... } else if (state === "error") { // ... } else if (state === "loaded") { // ... }
switch (state.isLoaded) { case true: // ... break; case false: // ... switch (state.errorOccurred) { case true: // ... break; case false: // ... break; } // ... break; }
Здесь становится ясно, что разница между if
и switch
не в синтаксисе. Речь идет о ментальной модели. Хочу ли я принимать решения на основе того, является ли какое-то выражение истинным, или я хочу обнаружить все возможные состояния и назначить им различные варианты поведения?
Что действительно интересно, так это то, что процесс выявления состояния - это только первый шаг. Хотя switches
ясно представляют все состояния, они скрывают изменения состояния.
Если мы добавим список возможных событий, вызывающих переходы между состояниями, в список возможных состояний, мы получим конечный автомат. И если мы строим наше программирование на конечном автомате, мы автоматные программисты!
Первоначально опубликовано на lukaszmakuch.pl 5 июня 2018 г.
✉️ Подпишитесь на рассылку еженедельно Email Blast от CodeBurst 🐦 Подпишитесь на CodeBurst на Twitter , просмотрите 🗺️ Дорожная карта веб-разработчиков на 2018 год и 🕸️ Изучите веб-разработку с полным стеком .