Будут ли проверяться все оставшиеся кейсы внутри инструкции switch если уже было найдено совпадение

Раздел:
Сайтостроение /
JavaScript /

Что такое JavaScript

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

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

>>> JavaScript, jQuery и Ajax с нуля до гуру >>>

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

var x = 1;

if (x == 1) 
{
  document.write("x = 1 <br>"); 
}
else 
{
  if (x == 2) 
  {
    document.write("x = 2 <br>"); 
  }
  else 
  {
    if (x == 3) 
    {
      document.write("x = 3 <br>"); 
    }
    else 
    {
      document.write("x = " + x + "<br>"); 
    } //if (x == 3)
  }   //if (x == 2)
}     //if (x == 1)

Это вполне допустимая с точки зрения синтаксиса конструкция. Этот код будет правильно работать — можете сами убедиться. И есть только одно “но” — такой исходный код слишком сложен и часто малопонятен. По этой причине совершить ошибку в таком коде можно довольно легко. Хорошо, что есть такая штука, как…

Оператор switch в JavaScript

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

Оператор switch (иногда это называют “инструкция switch”)
выполняет выбор того или иного участка кода для исполнения, в зависимости от
значения проверяемой переменной.

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

var x = 1;

switch(x) 
{
  case 1 :
    document.write("x = 1 <br>"); 
    break;
    
  case 2 :
    document.write("x = 2 <br>"); 
    break;
    
  case 3 :
    document.write("x = 3 <br>"); 
    break;
    
  default :
    document.write("x = " + x + "<br>");
    break; 
}

Оператор switch(x) проверяет значение переменной x,
и сравнивает его со значениями, указанными после слов case.
Если он находит совпадение, то выполняет исходный код, который находится
после case. Если совпадения не найдены, то выполняется код по умолчанию,
который находится после слова default.

Слово default не является обязательным. Если его нет, то в случае отсутствия совпадений просто ничего не происходит, и сценарий выполняется дальше.

ВАЖНО!
Обратите внимание на ключевое слово break. Если его не использовать,
то после первого нахождения совпадения все последующие инструкции будут выполнены, а не только тот блок, где найдено совпадение. Например, вот такой сценарий:

var x = 2;

//Использование switch без break

switch(x) 
{
  case 1 :
    document.write("x = 1 <br>");
    
  case 2 :
    document.write("x = 2 <br>"); 
    
  case 3 :
    document.write("x = 3 <br>"); 
    
  default :
    document.write("x = " + x + "<br>");
}

выведет на экран:

x = 2
x = 3
x = 2

ПРИМЕЧАНИЕ
Меня, как человека, начинавшего изучение программирования с Паскаля,
такое поведение оператора выбора всегда сильно бесило. Но JavaScript создан
на основе С/С++, поэтому вобрал в себя почти все их заморочки.

Использование switch в функциях

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

Если же вы используете switch в функции, то можно слово break
не применять, а обойтись только инструкцией return. Пример:

function TestSwitch(op, x, y)
{
  switch(op) 
  {
    case '+' :
      return(x + y);
      
    case '-' :
      return(x - y);
      
    case '*' :
      return(x * y);
      
    default :
      return("Неизвестная операция");
  }
}

document.write(TestSwitch('+', 1, 2));

Этот пример выведет на экран число 3.

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

ПРИМЕЧАНИЕ
Слово default в наших примерах указывается в конце блока switch.
Это соответствует логике, однако это не обязательно делать так, потому что default
в JavaScript можно располагать в любом месте блока switch.

Эта статья — лишь капля в море знаний о JavaScript. Если хотите испить эту чашу до дна, то изучить этот язык, а также jQuery и Ajax можно здесь:

>>> JavaScript, jQuery и Ajax с нуля до гуру >>>

Программирование на JavaScript

Видеокурс о программировании на JavaScript. Содержит 8 больших разделов от основ до работы с сетевыми запросами.
В комплекте 5 подарков — мини-курсов по темам, связанным с сайтостроением. 72 урока продолжительностью более 13 часов.
Упражнения и примеры исходных кодов. Поддержка от автора.
Подробнее…

Swift предоставляет цикл for-in, который упрощает итерацию по массивам, словарям, диапазонам, строкам и другим последовательностям.

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

Циклы For-in

Цикл for-in используется для итерации по коллекциям элементов, таких как диапазоны чисел, элементы массива или символы в строке.

Можно использовать цикл for-in вместе с массивом для итерации по его элементам:

let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!

Таким же образом вы можете производить итерацию по словарю, чтобы получить доступ к его паре ключ-значение. Когда происходит итерация по словарю, каждый его элемент возвращается как кортеж (ключ, значение). Вы можете разложить члены кортежа на отдельные константы для того, чтобы использовать их в теле цикла for-in. Здесь ключи словаря распадаются в константу animalName, а его значения — в константу legCount:

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
    print("\(animalName)s have \(legCount) legs")
}
// ants have 6 legs
// cats have 4 legs
// spiders have 8 legs

Содержимое словаря по сути своей не является упорядоченным, поэтому и извлекаемые из него значения во время итерации тоже могут быть не упорядочены. Более подробно о массивах и словарях смотрите в главе Типы Коллекций.

Вы так же можете использовать for-in с числовыми диапазонами. Следующий пример напечатает несколько первых значений таблицы умножения на 5:

for index in 1...5 {
    print("\(index) умножить на 5 будет \(index * 5)")
}
// 1 умножить на 5 будет 5
// 2 умножить на 5 будет 10
// 3 умножить на 5 будет 15
// 4 умножить на 5 будет 20
// 5 умножить на 5 будет 25

Коллекция элементов, по которой происходит итерация, является закрытым диапазоном чисел от 1 до 5 включительно, так как используется оператор закрытого диапазона(). Значение index устанавливается в первое число из диапазона (1), и выражение внутри цикла выполняются. В данном случае, цикл содержит только одно выражение, которое печатает запись из таблицы умножения на пять для текущего значения index. После того как выражение выполнено, значение index обновляется до следующего значения диапазона (2), и функция print(_:separator:terminator:) снова вызывается. Этот процесс будет продолжаться до тех пор, пока не будет достигнут конец диапазона.

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

Если Вам не нужно каждое значение из диапазона, то вы можете игнорировать их, используя символ подчёркивания вместо имени переменной:

let base = 3
let power = 10
var answer = 1
for _ in 1...power {
    answer *= base
}
print("\(base) в степени \(power) равно \(answer)")
// Выведет "3 в степени 10 равно 59049"

В этом примере вычисляется значение одного числа возведенное в степень другим (в данном случае 3 в степени 10). Начальное значение 1 (то есть 3 в степени 0) умножается на 3 десять раз, используя закрытый диапазон значений, который начинается с 1, и заканчивается 10. В данном случае нет необходимости знать значения счётчика во время каждой итерации цикла — он просто должен выполниться необходимое количество раз. Символ подчёркивания «_» (который используется вместо переменной цикла) игнорирует ее отдельные значения и не предоставляет доступ к текущему значению во время каждой итерации цикла.

В некоторых случаях вы можете не захотеть использовать замкнутый диапазон, который включает в себя оба конечных значения диапазона. Предположим, что вы хотите отрисовать минутные значения в виде черточек на часах. Вы будете рисовать 60 таких отметок, начиная с 0 минуты. Используйте полузамкнутый диапазон ( ..<), чтобы включить нижнюю границу, но не верхнюю. Для более подробного изучения диапазонов вам нужно перейти в главу Операторы диапазона.

let minutes = 60
for tickMark in 0..

Некоторые пользователи, возможно, захотят иметь поменьше минутных делений, и, предположим, они захотят иметь отметки на циферблате только на каждые 5 минут. Для того, чтобы у нас была возможность пропустить ненужные временные отметки используйте функцию stride(from:to:by:).

let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    // render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
}

Так же вы можете работать и с закрытыми диапазонами, но уже при помощи метода stride(from:through:by:):

let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    // render the tick mark every 3 hours (3, 6, 9, 12)
}

Циклы While

Цикл while выполняет набор инструкций до тех пор, пока его условие не станет false. Этот вид циклов лучше всего использовать в тех случаях, когда количество итераций до первого входа в цикл неизвестно. Swift предлагает два вида циклов while:

  • while — вычисляет условие выполнения в начале каждой итерации цикла.
  • repeat-while — вычисляет условие выполнения в конце каждой итерации цикла.

While

Цикл while начинается с вычисления условия. Если условие истинно, то инструкции в теле цикла будут выполняться до тех пор, пока оно не станет ложным.

Общий вид цикла while выглядит следующим образом:

  1. while условие {
  2. инструкции
  3. }

В этом примере показана простая игра Змеи и Лестницы (также известная, как Горы и Лестницы):

Игра проходит по следующим правилам:

  • Доска разделена на 25 квадратов и цель состоит в том, чтобы стать на 25-ый квадрат или за его пределами.
  • Игрок начинает с «нулевого квадрата», который расположен в самом левом нижнем углу доски.
  • В начале каждого хода вы бросаете игральную кость и перемещаетесь на то число шагов, которое выпало после броска, в направлении, которое указывает пунктирная стрелка.
  • Если ваш ход заканчивается на основании лестницы, то вы поднимаетесь по ней вверх.
  • Если ваш ход заканчивается на голове змеи, то вы спускаетесь вниз по хвосту змеи.

Игровая доска в примере представлена массивом значений типа Int. Его размер хранится в константе finalSquare, которая используется как для инициализации массива, так и для проверки условия победы. Т.к. игроки стартуют за пределами доски, с «нулевого квадрата», игровое поле инициализируется 26-ю, а не 25-ю целочисленными нулевыми значениями(каждое с индексом от 0 до 25 включительно):

let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)

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

board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

Квадрат 3 с основанием лестницы перемещает вас вверх на 11 квадрат. Чтобы это сделать, элементу массива board[03] присваивается +08, что эквивалентно значению 8 типа Int (разница между 3 и 11). Для того чтобы уточнить формулировку игрового поля, оператор унарного плюса (+i) уравновешивает оператор унарного минуса (-i), а числам ниже 10 приписаны нули. (В этих двух стилистических надстройках нет прямой необходимости, но они делают код более читаемым).

var square = 0
var diceRoll = 0
while square < finalSquare {
  // бросок кубика
  diceRoll += 1
  if diceRoll == 7 { diceRoll = 1 }
  // начать ходить на выпавшее количество шагов
  square += diceRoll
  if square < board.count {
    // если мы все еще на поле, идти вверх или вниз по змеям или лестницам
    square += board[square]
  }
}
print("Game over!")

Данный пример использует самый простой подход к реализации броска кубика. Вместо использования генератора случайных чисел, значение diceRoll начинается с 0. Каждую итерацию цикла переменная diceRoll увеличивается на 1 с помощью инфиксного оператора (+= 1), после чего проверяется не стало ли её значение слишком большим. Возвращаемое значение += diceRoll равно значению переменной diceRoll после её инкрементирования. Когда это значение становится равным 7, оно сбрасывается на 1. В итоге мы получаем последовательность значений diceRoll, которая всегда будет выглядеть следующим образом: 1, 2, 3, 4, 5, 6, 1, 2 и так далее.

После броска кубика игрок перемещается вперед на количество клеток, равное значению переменной diceRoll. Возможен случай, когда бросок кубика может переместить игрока за пределы квадрата 25. В таком случае игра заканчивается. Для того чтобы справиться с таким сценарием, код проверяет что значение square меньше чем свойство count массива board перед прибавлением значения, хранящегося в board[square] к текущему значению square для перемещения игрока вверх или вниз по змеям или лестницам.

Заметка

Если бы этой проверки не было, могла бы произойти попытка обращения к значению board[square], находящемуся за границами массива board, что привело бы к вызову ошибки. Если square равно 26, код попытается проверить значение board[26], которое выходит за границы массива.

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

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

Цикл repeat-while

Другой вариант цикла while, известный как цикл repeat-while, выполняет одну итерацию до того, как происходит проверка условия. Затем цикл продолжает повторяться до тех пор, пока условие не станет false.

Заметка

Цикл repeat-while в Swift аналогичен циклу do-while в других языках.

Общий вид цикла repeat-while выглядит следующим образом:

  1. repeat {
  2. инструкции
  3. } while условие

Ниже снова представлен пример игры Змеи и Лестницы , написанный с использованием цикла repeat-while. Значения переменных finalSquare, board, square и diceRoll инициализированы точно таким же образом, как и в случае с циклом while:

let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

В этой версии игры в начале цикла происходит проверка на наличие змей или лестниц на квадрате. Ни одна лестница на поле не приведет игрока на квадрат 25. Таким образом невозможно победить в игре, переместившись вверх по лестнице. Следовательно, такая проверка в самом начале цикла является абсолютно безопасной.

В начале игры игрок находится на квадрате 0. board[0] всегда равняется 0 и не оказывает никакого влияния:

repeat {
  // идти вверх или вниз по змеям или лестницам
  square += board[square]
  // бросить кубик
  diceRoll += 1
  if diceRoll == 7 { diceRoll = 1 }
  // начать ходить на выпавшее количество шагов
  square += diceRoll
} while square < finalSquare
print("Game over!")

После проверки на наличие змей и лестниц происходит бросок кубика и игрок продвигается вперед на количество квадратов, равное diceRoll. После этого текущая итерация цикла заканчивается.

Условие цикла (while square < finalSquare) такое же, как раньше, но в этот раз оно не вычисляется до окончания первого запуска цикла. Структура цикла repeat-while лучше подходит для этой игры, чем цикл while в предыдущем примере. В цикле repeat-while выше square += board[square] всегда выполняется сразу, в то время как в цикле while происходит проверка того, что square все еще находится на поле. Такой принцип работы цикла repeat-while снимает необходимость проверки выхода за границы массива, которую мы видели в предыдущей версии игры.

Условные инструкции

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

Swift предоставляет нам два варианта добавить условные ответвления кода — это при помощи инструкции if и при помощи инструкции switch. Обычно мы используем инструкцию if, если наше условие достаточно простое и предусматривает всего несколько вариантов. А вот инструкция switch подходит для более сложных условий, с многими вариантами выбора, и очень полезна в ситуациях, где по найденному совпадению с условием и выбирается соответствующая ветка кода для исполнения.

Инструкция if

В самой простой своей форме инструкция if имеет всего одно условие if. Эта инструкция выполняет установленные инструкции только в случае, когда условие true:

var temperatureInFahrenheit = 30
if temperatureInFahrenheit <= 32 {
     print ("It's very cold. Consider wearing a scarf.")
}
// Выведет "It's very cold. Consider wearing a scarf.

В приведенном примере проверяется значение температуры, которая может быть ниже или 32 (0 по Цельсию) градусов по Фаренгейту либо равна или выше. Если она ниже, то выведется сообщение. В противном случае никакого сообщения не будет, и код продолжит свое выполнение после закрывающей фигурной скобки инструкции if.

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

temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}
// Выведет "It's not that cold. Wear a t-shirt."

В этом коде всегда будет выполняться код либо в первом, либо во втором ответвлении. Из-за того что температура выросла до 40 градусов Фаренгейта, значит больше не обязательно носить шарф, таким образом ответвление else выполняется.

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

temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}
// Выведет "It's really warm. Don't forget to wear sunscreen.

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

Последняя else опциональна и может быть удалена, если в ней нет необходимости:

temperatureInFahrenheit = 72
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
}

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

Инструкция switch

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

В самой простой форме в инструкции switch значение сравнивается с одним или более значений того же типа:

switch значение для сопоставления {
     case значение 1: 
          инструкция для значения 1
     case значение 2, значение 3:
          инструкция для значения 2 или значения 3
     default: 
          инструкция, если совпадений с шаблонами не найдено
}

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

Тела каждого отдельного блока case в switch — это отдельная ветка исполнительного кода, что делает switch похожим на инструкцию if. Инструкция switch определяет какое ответвление должно быть выбрано. Это известно как переключение на значение, которое в настоящее время рассматривается.

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

В следующем примере switch рассматривает единичный символ в нижнем регистре, который называется someCharacter:

let someCharacter: Character = "z"
switch someCharacter {
case "a":
    print("The first letter of the alphabet")
case "z":
    print("The last letter of the alphabet")
default:
    print("Some other character")
}
// Выведет "The last letter of the alphabet"

Первый кейс инструкции switch соответствует первой букве английского алфавита — a, второй кейс соответствует последней букве — z. Так как switch должна иметь кейс для каждого возможного символа, а не просто для каждой буквы алфавита, то в инструкции switch предусмотрен дефолтный кейс, который звучит как default, в который входят все символы кроме и z. Как раз это условие гарантирует, что инструкция switch будет исчерпывающей.

Отсутствие case-провалов

Большое отличие инструкции switch в языке Swift от инструкции switch в C и Objective-C составляет отсутствие провалов через условия. Вместо этого инструкция switch прекращает выполнение после нахождения первого соответствия с case и выполнения соответствующего кода в ветке, без необходимости явного вызова break. Это делает инструкцию switch более безопасным и простым для использования, чем в C, и исключает исполнение кода более чем одного случая.

Заметка

Хотя break не требуются в Swift, вы все равно можете его использовать для соответствия и для игнорирования конкретного случая или просто для выхода из конкретного случая, еще до того, как исполнится код. Более детально можно прочитать в разделе Оператор Break в инструкции Switch.

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

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a":  // ошибка, так как кейс имеет пустое тело
case "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// ошибка компиляции

В отличии от инструкции switch в языке C, switch в Swift не соответствует ни «a», ни «A». Но зато вы получите ошибку компиляции о том, что case «a»: не содержит ни одного исполняемого выражения. Такой подход исключает случайные «проваливания» из одного случая в другой, что делает код безопаснее и чище своей краткостью.

Для того, чтобы switch с одним кейсом подходил под «a» и «A»,объедините два значения в один составной кейс, разделив значения запятыми.

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
    print("The letter A")
default:
    print("Not the letter A")
}
// Выведет "The letter A"

Для того, чтобы составной кейс удобно было читать, он может быть написан несколькими строчками. Более подробно далее в «Составные Кейсы».

Заметка

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

Соответствие диапазону

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

let approximateCount = 62
let countedThings = "moons orbiting Saturn"
var naturalCount: String
switch approximateCount {
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
case 12..<100:
    naturalCount = "dozens of"
case 100..<1000:
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// Выводит "There are dozens of moons orbiting Saturn."

В приведенном выше примере, approximateCount оценивается в инструкции switch. Каждый кейс сравнивает это значение с числом или интервалом. Поскольку значение approximateCount попадает на диапазон от 12 до 100, naturalCount присваивается значение «dozens of», и исполнение перемещается из инструкции switch.

Кортежи

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

Пример ниже берет точку с координатами (x, y), выраженную в виде кортежа (Int, Int) и относит к соответствующей категории как следует из примера ниже:

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    print("\(somePoint) is at the origin")
case (_, 0):
    print("\(somePoint) is on the x-axis")
case (0, _):
    print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
    print("\(somePoint) is inside the box")
default:
    print("\(somePoint) is outside of the box")
}
// Выведет "(1, 1) is inside the box"

Инструкции switch определяет: находится ли точка в начале отсчета (0,0), на красной оси x, на оранжевой оси y, внутри синего квадрата 4х4, в котором точка отсчета находится в центре или находится вне этого квадрата.

В отличии от C, инструкция switch в Swift позволяет множественное совпадение или пересечение значений нескольких случаев. Это факт, что точка (0, 0) соответствует всем четырем условиям в этом примере. Однако, если возможно совпадение сразу с несколькими шаблонами, то в расчет принимается только первое из них. То есть точка (0, 0) будет удовлетворять случаю case (0, 0):, а остальные случаи будут проигнорированы.

Привязка значений

Кейс в инструкции switch может связывать значение или значения, с которыми сравнивается, с временными константами или переменными. Это известно как связывание значений, потому что значения «связаны» с временными константами или переменным внутри тела кейса.

Пример ниже берет точку с координатами (x, y), представленной в виде кортежа (Int, Int) и определяет ее позицию на графике, который представлен ниже:

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of \(x)")
case (0, let y):
    print("on the y-axis with a y value of \(y)")
case let (x, y):
    print("somewhere else at (\(x), \(y))")
}
// Выведет "on the x-axis with an x value of 2

Инструкция switch определяет лежит ли точка на красной оси x или оранжевой оси y, а может быть она не будет ни на одной из осей.

Три случая в инструкции switch объявляют константы x, y, которым временно присваиваются значения одного или обоих элементов из кортежа anotherPoint. В первом кейсе (let x, 0): подойдет любая точка со значением y равным 0, а в константу x запишется значение координаты x нашей точки. Аналогично и во втором случае, когда case (0, let y), этот кейс включает все точки при значении их координаты x равной 0, и происходит присваивание значения координаты y в временную константу y.

Объявленная константа может быть использована внутри блока кейса. Здесь мы их используем как сокращенный вариант для вывода сообщения с помощью функции print.

Заметьте, что инструкция switch не имеет случая default. Последний кейс let (x, y) объявляет кортеж двух констант плейсхолдеров, которые могут соответствовать абсолютно любому значению. Так как anotherPoint это кортеж с двумя значениями, этот кейс подходит под все возможные оставшиеся значения, и кейс default уже не нужен, так как инструкция switch исчерпывающая.

Where

В кейсе инструкции switch мы так же можем использовать дополнительное условие с помощью ключевого слова where.

Пример ниже размещает точку (x, y) на приведенном рисунке:

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// Выведет "(1, -1) is on the line x == -y"

Инструкция switch определяет лежит ли точка на зеленой диагонали, где x == y, или фиолетовой диагонали, где x == -y, или ни на одной и ни на другой.

Три кейса объявляют константы x, y, которые временно берут значения из кортежа yetAnotherPoint. Эти константы используются как часть условия where, для создания динамического фильтра. Кейс switch совпадает с текущим значением point только в том случае, если условие оговорки where возвращает true для этого значения.

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

Составные кейсы

Если несколько кейсов инструкции switch содержат один и тот же код для исполнения, то шаблоны этих кейсов можно объединить через запятую после ключевого слова case. Если хотя бы один из шаблонов кейса соответствует сравниваемому значению, то значит и сам кейс соответствует сравниваемому значению. Шаблоны в кейсе могут быть записаны на несколько строк, если их очень много. Например:

let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
    print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
     "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
    print("\(someCharacter) is a consonant")
default:
    print("\(someCharacter) is not a vowel or a consonant")
}
// Напечатает "e is a vowel"

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

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

let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
    print("On an axis, \(distance) from the origin")
default:
    print("Not on an axis")
}
// Напечатает "On an axis, 9 from the origin"

Кейс выше имеет два шаблона: (let distance, 0), который соответсвует любой точке на оси x, и (0, let distance), что соответствует точке на оси y. И тот и другой шаблон включают в себя привязку для distance и distance является целочисленным значением для двух этих шаблонов, что значит, что код внутри тела кейса всегда будет иметь доступ к значению distance.

Операторы передачи управления

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

  • continue
  • break
  • fallthrough
  • return
  • throw

Операторы continue, break, fallthrough будут описаны в следующих главах, оператор return будет описан в главе Функции, а оператор throw будет описан в Передача ошибки с помощью генерирующей функции.

Оператор Continue

Оператор continue говорит циклу прекратить текущую итерацию и начать новую. Он как бы говорит: «Я закончил с текущей итерацией», но полностью из цикла не выходит.

Следующий пример убирает все пробелы и гласные в нижнем регистре из строки, для того чтобы создать загадочную фразу-головоломку:

let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
    if charactersToRemove.contains(character) {
        continue
    } else {
        puzzleOutput.append(character)
    }
}
print(puzzleOutput)
// Выведет "grtmndsthnklk"

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

Оператор Break

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

Оператор Break в цикле

Когда оператор break используется внутри цикла, то он немедленно прекращает работу цикла, и выполнение кода продолжается с первой строки после закрывающей скобки цикла (}). Никакой последующий код из текущей итерации цикла выполняться не будет, и никакие дальнейшие итерации цикла не будут запускаться.

Оператор Break в инструкции Switch

Когда оператор break используется внутри инструкции switch, то он прекращает исполнение кода конкретного случая и перекидывает исполнение на первую строку после закрывающей скобки (}) инструкции switch.

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

Заметка

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

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

let numberSymbol: Character = "三"  // Цифра 3 в упрощенном Китайском языке
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
    possibleIntegerValue = 1
case "2", "٢", "二", "๒":
    possibleIntegerValue = 2
case "3", "٣", "三", "๓":
    possibleIntegerValue = 3
case "4", "٤", "四", "๔":
    possibleIntegerValue = 4
default:
    break
}
if let integerValue = possibleIntegerValue {
    print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
    print("An integer value could not be found for \(numberSymbol).")
}
// Выведет "The integer value of 三 is 3."

Этот пример проверяет numberSymbol на наличие в нем целого числа от 1 до 4 на арабском, латинском, китайском или тайском языках. Если совпадение найдено, то один из кейсов switch устанавливает опциональную переменную Int?, названную possibleIntegerValue в подходящее целочисленное значение.

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

Так как в примере выше не практично перечислять каждое возможное значение Character, то кейс default улавливает все остальные варианты символов, которые не соответствуют первым четырем кейсам. Кейсу default не надо предпринимать какие-либо действия, так что там прописан только оператор break. После того как срабатывает кейс default, срабатывает и break, что прекращает действие инструкции switch и код продолжает свою работу с if let.

Оператор Fallthrough

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

Если вам по какой-то причине нужно аналогичное проваливание как в C, то вы можете использовать оператор fallthrough в конкретном кейсе. Пример ниже использует fallthrough для текстового описания целого числа:

let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " a prime number, and also"
    fallthrough
default:
    description += " an integer."
}
print(description)
// Выведет "The number 5 is a prime number, and also an integer."

В примере мы объявляем новую переменную типа String, названную description и присваиваем ей исходное значение. Потом мы определяем величину integerToDescribe, используя инструкцию switch. Если значение integerToDescribe одно из значений списка кейса, то мы получаем текстовое описание значения, которое дополняется значением, которое находится в default, так как на уровень выше в сработавшем кейсе стоит ключевое слово fallthrough, после чего завершается работа инструкции switch.

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

После того как сработала инструкция switch, мы получаем описание числа, используя функцию print(_:separator:terminator:). В нашем примере мы получаем 5, что корректно определено как простое число.

Заметка

Ключевое слово fallthrough не проверяет условие кейса, оно позволяет провалиться из конкретного кейса в следующий или в default, что совпадает со стандартным поведением инструкции switch в языке C.

Маркированные инструкции

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

Для всех этих целей мы можем маркировать цикл или инструкцию switch маркером инструкций и использовать его вместе с оператором break или оператором continue для предотвращения или продолжения исполнения маркированной инструкции.

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


имя маркера: while условие {
     исполняемый код
}

В дальнейшем примере мы будем использовать break, continue с маркированным циклом while для адаптированной версии Змеи и Лестницы, которую вы видели ранее в «Циклы While». В этот раз у нас появилось новое правило:

  • Чтобы победить вы должны попасть точно на клетку 25.

Если результат броска кубика дает вам ходов более чем на 25 клетку, то вы должны бросить еще раз, до тех пор, пока не попадете точно на клетку 25.

Игровая зона доски осталась такой же как и была:

Величины finalSquare, board, square и diceRoll инициализируются точно так же как и в прошлых примерах игры:

let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

В этой версии игры используется цикл while и инструкция switch для воплощения логики игры. Цикл while маркер названный gameLoop, для индикации главного цикла игры.

Условие цикла while square != finalSquare показывает, что теперь нам нужно попасть строго на клетку 25:

gameLoop: while square != finalSquare {
    diceRoll += 1
    if diceRoll == 7 { diceRoll = 1 }
    switch square + diceRoll {
    case finalSquare:
        //после броска кубика мы попадаем на клетку 25, игра окончена
        break gameLoop
    case let newSquare where newSquare > finalSquare:
         //мы кинули кубик на слишком большое значение, значит нам нужно кинуть снова
        continue gameLoop
    default:
        //допустимое движение по игровому полю, двигаемся
        square += diceRoll
        square += board[square]
    }
}
print("Game over!")

Игральная кость бросается в начале каждого цикла. Прежде чем двигаться по доске идет проверка в инструкции switch на валидность хода, потом обрабатывает его, если такое движение допустимо:

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

Заметка

Если оператор break не использует маркер gameLoop, то он будет прерывать выполнение инструкции switch, а не всего цикла while. Но используя маркер gameLoop мы можем указать какое исполнение инструкции нужно прервать.

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

Ранний выход

Инструкция guard, как и инструкция if, выполняет выражения в зависимости от логического значения условия. Используйте guard, чтобы указать на то, что условие обязательно должно быть true, чтобы код после самой инструкции guard выполнился. В отличии от инструкции if, guard всегда имеет код внутри else, который выполняется, когда условие оценивается как false.

func greet(person: [String: String]) {
  guard let name = person["name"] else {
    return
  }
  
  print("Привет \(name)!")
  
  guard let location = person["location"] else {
    print("Надеюсь у тебя там хорошая погода.")
    return
  }
  
  print("Надеюсь в \(location) хорошая погода.")
}

greet(person: ["name": "John"])
// Выведет "Привет John!"
// Выведет "Надеюсь у тебя там хорошая погода."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Выведет "Привет Jane!"
// Выведет "Надеюсь в Cupertino хорошая погода.”

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

Если условие не выполняется, то исполняется код внутри else. Эта ветка должна перебросить исполнение кода на выход из этого блока кода, в котором был определен guard. А сделать это можно при помощи инструкций return, break, continue, throw или можно вызвать метод, который ничего не возвращает, например fatalError(_file:line:).

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

Проверка доступности API

В Swift есть встроенная поддержка для проверки доступности API, благодаря которой вы будете уверены, что не используете  API-интерфейсы, недоступные для данной deployment target.

Компилятор использует информацию о доступности в SDK, чтобы убедиться, что все API-интерфейсы, используемые в коде, доступны для deployment target, указанного в вашем проекте. Swift выдает сообщение об ошибке во время компиляции, если вы пытаетесь использовать недоступный API.

Вы можете использовать условие доступности в if или guard инструкциях для того, чтобы условно выполнить блок кода, в зависимости от того, доступны ли API-интерфейсы, которые вы хотите использовать, во время выполнения. Компилятор использует информацию из условия доступности, когда проверяет доступность API-интерфейсов в этом блоке кода.

if #available(iOS 10, macOS 10.12, *) {
    // Используйте API iOS 10 для iOS и используйте API macOS 10.12 на macOS
} else {
    // Используйте более старые API для iOS и macOS
}

Условие доступности выше указывает, что на iOS тело if выполняется только на iOS 10 и более поздних версиях; что касается macOS: только на macOS 10.12 и более поздних версиях. Последний аргумент, *, требует и указывает, что на любой другой платформе, тело if выполняется на минимальной указанной deployment target.

В общем виде условие доступности принимает список названий платформ и версий. Вы можете использовать названия платформы, такие как iOSmacOSwatchOS, и tvOS; полный список можно найти в Атрибуты объявлений. В дополнение к определению основных номеров версий, такие как iOS 8 или macOS 10.10, вы можете указать второстепенные версии номера, такие как iOS 8.3 и macOS 10.10.3.

  1. if #available (название платформы версия платформы, , * ) {
  2. выражения для исполнения, если соответствующие условию API доступны
  3. } else {
  4. выражения для исполнения, если соответствующие условию API недоступны
  5. }

Условные конструкции

Последнее обновление: 23.10.2023

Условные конструкции позволяют выполнить те или иные действия в зависимости от определенных условий.

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

Конструкция if..else проверяет некоторое условие и если это условие верно, то выполняет некоторые действия.
Простейшая форма конструкции if..else:

if(условие){
	
	некоторые действия
}

После ключевого слова if в круглых скобках идет условие, а после условия — блок кода с некоторыми действиями.
Если это условие истинно, то затем выполняются действия, которые помещены в блоке кода

Например:

const income = 100;
if(income > 50) {
	
	console.log("доход больше 50");
}

Здесь в конструкции if используется следующее условие: income > 50. Если это условие возвращает true, то есть если константа income имеет значение больше 50,
то браузер отображает сообщение. Если же значение income меньше 50, то никакого сообщения не отображается.

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

const income = 100;
if(income > 50) console.log("доход больше 50");

или перенести действия на следующую строку

const income = 100;
if(income > 50) 
	console.log("доход больше 50");

Причем условия могут быть сложными:

const income = 100;
const age = 19;
if(income > 50 && age > 18){

	console.log("доход больше 50");
	console.log("возраст больше 18");
}

Проверка наличия значения

Конструкция if позволяет проверить наличие значения. Например:

let myVar = 89;
if(myVar){
	
	console.log(`Переменная myVar имеет значение: ${myVar}`);
}

Если переменная myVar имеет значение, как в данном случае, то в условной конструкции она возвратит значение true.

Противоположный вариант:

let myVar;
if(myVar){
    console.log(`Переменная myVar имеет значение: ${myVar}`);
}

Здесь переменная myVar не имеет значения. (В реальности она равна undefined) Поэтому условие в конструкии if возвратит
false, и действия в блоке конструкции if не будут выполняться.

Но нередко для проверки значения переменной используют альтернативный вариант — проверяют на значение undefined и null:

if (myVar !== undefined && myVar !== null) {
	console.log(`Переменная myVar имеет значение: ${myVar}`);
}

Выражение else

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

if(условие){
	действия, если условие истинно
}
else{
	действия, если условие ложно
}

То есть если условие после if истинно, выполняется блок if. Если условие ложно, выполняется блок else. Например:

const income = 45;
if(income > 50){

	console.log("Доход больше 50");
}
else{
	console.log("Доход меньше или равен 50");
}

Здесь константа income равна 45, поэтому условие после оператора if возвратит false,
и управление перейдет к блоку else.

Также если блок else содержит одну инструкцию, то можно сократить конструкцию:

const income = 45;
if(income > 50) console.log("Доход больше 50");
else console.log("Доход меньше или равен 50");

Альтернативные условия и else if

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

const income = 50;
if(income > 50) {
	console.log("Доход больше 50");
}
else if(income === 50){
	console.log("Доход равен 50");
}
else{
	console.log("Доход меньше 50");
}

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

const income = 500;
if(income < 200){

	console.log("Доход ниже среднего");
}
else if(income>=200 && income<300){
	
	console.log("Чуть ниже среднего");
}
else if(income>=300 && income<400){
	
	console.log("Средний доход");
}
else{
	console.log("Доход выше среднего");
}

При этом блок else применять необязательно:

const income = 500;
if(income < 200){

	console.log("Доход ниже среднего");
}
else if(income>=200 && income<300){
	
	console.log("Чуть ниже среднего");
}
else if(income>=300 && income<400){
	
	console.log("Средний доход");
}

True или false

В javascript любая переменная может применяться в условных выражениях, но не любая переменная представляет тип boolean. И в этой связи
возникает вопрос, что возвратит та или иная переменная — true или false? Много зависит от типа данных, который представляет переменная:

  • undefined

    Возвращает false

  • null

    Возвращает false

  • Boolean

    Если константа/переменная равна false, то возвращается false.
    Соответствено если константа/переменная равна true, то возвращается true

  • Number

    Возвращает false, если число равно 0 или NaN (Not a Number), в остальных случаях возвращается true

    Например, следующая переменная будет возращать false:

    let x = NaN;
    if(x){	// false
    		
    }
    
  • String

    Возвращает false, если константа/переменная равна пустой строке, то есть ее длина равна 0, в остальных случаях возвращается true

    const emptyText = "";	// false - так как пустая строка
    const someText = "javascript";	// true - строка не пустая
    
  • Object

    Всегда возвращает true

    const user = {name:"Tom"};	// true
    const car = {};	// true
    

Конструкция switch..case

Конструкция switch..case является альтернативой использованию конструкции if..else и также позволяет обработать сразу
несколько условий:

const income = 200;
switch(income){

	case 100 : 
		console.log("Доход равен 100");
		break;
	case 200 : 
		console.log("Доход равен 200");
		break;
	case 500 : 
		console.log("Доход равен 500");
		break;
}

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

В конце каждого блока сase ставится оператор break, чтобы избежать выполнения других блоков. В данном случае константа income равна 200, поэтому будет выполняться блок

case 200 : 
	console.log("Доход равен 200");
	break;

Оператор break

Оператор break служит для того, чтобы избежать выполнения других условий. Например, мы могли бы написать:

let income = 200;
switch(income){
 
    case 100 : 
        console.log("Доход равен 100");
		income +=100;
		break;
    case 200 : 
        console.log("Доход равен 200");
		income +=100;
		break;
    case 500 : 
        console.log("Доход равен 500");
		income +=100;
		// break;	// здесь смысла в break нет, так как последний блок
}

Здесь опять income равно 200 и опять будет выполняться блок

case 200 : 
    console.log("Доход равен 200");
	income +=100;
	break;

Благодаря оператору break после выполнения блока произойдет выход из конструкции switch, и никакие другие блоки case не будут выполняться.

Но теперь уберем оператор break:

let income = 200;
switch(income){
 
    case 100 : 
        console.log("Доход равен 100");
		income +=100;
    case 200 : 
		console.log("Доход равен 200");
		income +=100;
    case 500 :
		console.log("Доход равен 500");
		income +=100;
}
console.log("Финальный доход равен", income);

Результат выполнения:

Доход равен 200
Доход равен 500
Финальный доход равен 400

Здесь изначально переменная income опять равна 200, соответственно будет выполняться блок

case 200 : 
    console.log("Доход равен 200");
	income +=100;

Значение income увеличивается на 100, однако в конце блока нет оператора break, поэтому управление перейдет к проверке условия в следующий блок:

case 500 : 
    console.log("Доход равен 500");
	income +=100;

И не важно, что income не равно 500 (а лишь 300 на данный момент), этот блок также будет выполняться.

Объединение условий

Однако при необходимости можно сразу обработать несколько условий:

const income = 200;
switch(income){

	case 100 :
	case 200 :
		console.log("Доход равен 100 или 200");
		break;
	case 500 : 
		console.log("Доход равен 500");
		break;
}

В данном случае для условия, когда income равно 100 и 200, выполняются одни и те же действия.

Условие по умолчанию — default

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

const income = 700;
switch(income){

	case 100 : 
		console.log("Доход равен 100");
		break;
	case 200 : 
		console.log("Доход равен 200");
		break;
	case 500 : 
		console.log("Доход равен 500");
		break;
	default: 
        console.log("Доход неизвестной величины");
        break;
}

Антон Ларичев

Основатель школы PurpleSchool

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

Инструкция switch принимает выражение или значение и сравнивает его со “случаями”(case), перечисленными внутри нее, после чего выполняет весь код, описаный ниже подходящего “случая” до конца конструкции или до инструкции break.

Одним из ключевых отличий от конструкций if…else и подобных проверок на условие является то, что switch не завершает выполнение после нахождения совпадения, а продолжает работу до конца конструкции или до первой инструкции break. Поэтому важно не забывать указывать break, если на каждый “случай” должен отработать отдельный блок кода.

Сравниваемые значения сопоставляются строго (аналогично сравнению с помощью оператора ===) поэтому важно не только значение проверяемого выражения или переменной, но и их тип.

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

Как мы уже знаем, switch строго сравнивает выражения и не использует проверки как другие логические ветвления вроде if…else поэтому не выйдет указать в одном “случае” несколько вариантов через логические операторы. Вместо этого можно просто указать несколько “случаев” подряд с одним блоком кода и при совпадении одного из них этот код выполнится.

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

В примере выше мы видим 6 case 5 из которых сгруппированы с помощью инструкции break и при совпадении одного из них будет выполнено ожидаемое количество операций (только операции ниже совпавшего). Таким образом мы можем создавать последовательно выполняемый код, удобно разделяя его на части в зависимости от значения проверяемого выражения. Важно помнить что при таком подходе следует следить за правильным порядком перечисления “случаев”.

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

Блоки кода внутри switch необязательно заключать в фигурные скобки, как в if…else потому что конструкция рассматривает их как один большой блок, который начинает исполняться после подходящего case. Такое поведение можно изменить, обернув блоки кода в фигурные скобки. В таком случае каждый блок будет иметь свою область видимости.

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

JavaScript с нуля — основы языка и практика для начинающих

— 16 часов коротких лекций по 10 — 15 минут

— 15 упражнений для закрепления на практике1

— 5 тестов для проверки знаний

— Рейтинг ⭐ 4.9 на основании отзывов

— 30-ти дневная гарантия возврата денег

JavaScript Advanced — продвинутые концепции языка и ООП

— 18 часов коротких лекций по 10 — 15 минут

— 30упражнений для закрепления на практике

— 14 тестов для проверки знаний

— Рейтинг ⭐ 4.9 на основании отзывов

— 30-ти дневная гарантия возврата денег

решил таки объединить комментарии в ответ.


при таком «громоздком» и «разнообразном» содержимом кейсов, свич тут вообще не нужен.

то что <8 можно загнать в массив, типа var x = [сегодня, вчера, 2дня, 3дня...]

после if(diffs<7) console.log(x[diffs]); и 8-10 схлопнуть в еще один if.

впрочем можно и еще изящней…

заменить ifы тернарником и тогда все это безобразие спокойно обернётся одним единственным console.log(ну или функцией) вместо их кучи на разных ветках.

var ruTimes = // мульти-язык надо? :3
['несколько часов назад',
'1 день назад',
'2 дня назад',
'3 дня назад',
'4 дня назад',
'5 дней назад',
'6 дней назад',
'неделю назад',
'более недели назад',
'менее месяца назад',
'месяц назад',
'более месяца назад',
'несколько месяцев назад',
'менее полугода',
'более полугода',
'год назад',
'больше года назад',
'несколько лет назад',
'в скором будущем'];
function myTimes(x, d){var y =
d >= 0 && d < 8 ? x[d]:
d >= 8 && d < 14 ? x[8]:
d >= 14 && d < 28 ? x[9]:
d >= 28 && d < 32? x[10]: // февраль тоже месяц
d >= 32 && d < 63 ? x[11]:
d >= 63 && d < 94 ? x[12]:
d >= 94 && d < 183 ? x[13]:
d >= 183 && d < 365 ? x[14]:
d == 365 ? x[15]:
d > 365 && d < 365*2 ? x[16]:
d >= 365*2 ? x[17]:
d <= 0 ? x[18]: 'error'; return y;} //зато сниппет без скролла :3
<input type='number' placeholder='развлекайтесь ;)'
onchange='console.log(myTimes(ruTimes, this.value));'>

p.s. если производительности не жалко, можно в принципе массив и рекурсией\циклом прощупать, так еще компактнее выйдет :3

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Terra origin healthy gut инструкция по применению на русском языке
  • Манге в 6 форте инструкция по применению
  • Casio cdp 220r инструкция на русском языке
  • Изотин капли в глаза индия инструкция отзывы
  • Как зарегистрироваться на самозанятость через госуслуги пошаговая инструкция пошаговая