Кратко
СкопированоУправляющая конструкция switch
позволяет выполнять различные блоки кода, в зависимости от значения переменной.
Похож на if
, но решает более узкую задачу.
Как пишется
Скопированоswitch (имя_переменной_значение_которой_сравниваем) { case значение: // код break}
switch (имя_переменной_значение_которой_сравниваем) { case значение: // код break }
В круглых скобках указывается переменная, значение которой сравнивается. В фигурных скобках с помощью ключевого слова case
указываются возможные значения и код, который нужно выполнить.
Пример приветствия пользователя в зависимости от статуса:
switch (membershipStatus) { case 'vip': // выполнится, если в переменной membershipStatus хранится строка 'vip' console.log('Приветствуем вас, ваше великолепие!') console.log('рады вас видеть!') break case 'diamond': console.log('Здравствуйте, бриллиантовый клиент!') break case 'gold': console.log('Привет, золотой мой!') break default: // выполнится, если ни один другой случай не сработал console.log('Прив') break}
switch (membershipStatus) { case 'vip': // выполнится, если в переменной membershipStatus хранится строка 'vip' console.log('Приветствуем вас, ваше великолепие!') console.log('рады вас видеть!') break case 'diamond': console.log('Здравствуйте, бриллиантовый клиент!') break case 'gold': console.log('Привет, золотой мой!') break default: // выполнится, если ни один другой случай не сработал console.log('Прив') break }
Как понять
СкопированоВ программировании часто встречается задача выполнения разного кода в зависимости от какого-либо условия. Обычно, такие задачи решают с помощью конструкции if
.
Среди этих задач есть особый подтип — когда нужно посмотреть на значение переменной и выполнить разный код, в зависимости от этого значения. Например, применить разную скидку для клиентов разного статуса — самым любимым клиентам дать скидку 25%, с картой лояльности — 10%, а обычным покупателям не дать ничего.
Такую задачу тоже можно решить с помощью if
:
let discountif (memberStatus === 'vip') { discount = 0.25} else if (memberStatus === 'diamond') { discount = 0.2} else if (memberStatus === 'gold' || memberStatus === 'silver') { // скидка 10% пользователям статуса золотой и серебряный discount = 0.1} else { discount = 0}
let discount if (memberStatus === 'vip') { discount = 0.25 } else if (memberStatus === 'diamond') { discount = 0.2 } else if (memberStatus === 'gold' || memberStatus === 'silver') { // скидка 10% пользователям статуса золотой и серебряный discount = 0.1 } else { discount = 0 }
Код выше работает, но выглядит избыточно — в нем очень много сравнений с использованием member
. Конструкция switch
решает такую задачу меньшим объёмом кода:
let discountswitch (memberStatus) { case 'vip': discount = 0.25 break case 'diamond': discount = 0.2 break case 'gold': case 'silver': // можно написать несколько кейсов и связать с одним блоком discount = 0.1 break default: discount = 0 break}
let discount switch (memberStatus) { case 'vip': discount = 0.25 break case 'diamond': discount = 0.2 break case 'gold': case 'silver': // можно написать несколько кейсов и связать с одним блоком discount = 0.1 break default: discount = 0 break }
В круглых скобках указана переменная, значение которой нужно сравнивать с различными возможными значениями — кейсами. Порядок обычно не имеет значения.
Внутри кейса пишется список команд, которые нужно выполнить. Список команд завершается оператором break
.
Существует необязательный кейс default
, который срабатывает, если ни одно значение не подошло.
Что будет, если не поставить break
?
СкопированоЕсли вы забыли поставить break
, то будут выполнены все команды, начиная со сработавшего кейса и до тех пор, пока либо не встретится break
, либо не закончится switch
.
Сравните:
Выполняется весь код от текущего case
до следующего break
, даже если он вне текущего кейса.
В коде появился баг — значение для бриллиантового уровня будет установлено в 0
вместо 0
.
На практике
Скопированосоветует Скопировано
Есть когнитивное искажение, называемое «Закон инструмента»:
Если из инструментов у вас только молоток, всё вокруг кажется гвоздями
Так и switch
часто превращается в такой молоток. Конечно, у switch
есть свои преимущества: можно использовать разом несколько case
, в условиях можно написать различную логику и прочее.
function greet(role) { switch (role) { case 'admin': case 'moder': return 'Приветствую, смотритель порядка' case 'user': trackUserVisit() return 'Здравствуй, пользователь' case 'guest': return 'Здравствуй, гость' default: return 'Привет, некто' }}
function greet(role) { switch (role) { case 'admin': case 'moder': return 'Приветствую, смотритель порядка' case 'user': trackUserVisit() return 'Здравствуй, пользователь' case 'guest': return 'Здравствуй, гость' default: return 'Привет, некто' } }
Однако часто нам нужно просто соотнести одно значение с другим. И в таких случаях лучше завести словарь:
const roleToGreeting = { admin: 'Приветствую, босс', moder: 'Приветствую, смотритель порядка', user: 'Здравствуй, пользователь', guest: 'Здравствуй, гость',}const greetings = (role) => roleToGreeting[role] ?? 'Привет, некто'
const roleToGreeting = { admin: 'Приветствую, босс', moder: 'Приветствую, смотритель порядка', user: 'Здравствуй, пользователь', guest: 'Здравствуй, гость', } const greetings = (role) => roleToGreeting[role] ?? 'Привет, некто'
Есть ещё шаблон switch
, который якобы сокращает if
:
function getCategoryByAge(age) { switch (true) { case (age >= 0 && age <= 12): return "Child" case (age >= 13 && age <= 19): return "Teenager" case (age >= 20 && age <= 35): return "Young Adult" case (age >= 36 && age <= 55): return "Adult" case (age > 55): return "Senior" default: return "Invalid age" }}
function getCategoryByAge(age) { switch (true) { case (age >= 0 && age <= 12): return "Child" case (age >= 13 && age <= 19): return "Teenager" case (age >= 20 && age <= 35): return "Young Adult" case (age >= 36 && age <= 55): return "Adult" case (age > 55): return "Senior" default: return "Invalid age" } }
Использование switch
является спорным вопросом и выглядит скорее как хак, нежели задуманный сценарий использования языка. Также учтите, что вашим коллегам эта конструкция может быть непривычна, в отличие от обычных условий, которые понятны всем. Сторонники switch
утверждают, что он позволяет сократить код, но пример выше напротив будет более лаконичным без него:
function getCategoryByAge(age) { if (age >= 0 && age <= 12) return "Child" if (age >= 13 && age <= 19) return "Teenager" if (age >= 20 && age <= 35) return "Young Adult" if (age >= 36 && age <= 55) return "Adult" if (age > 55) return "Senior" return "Invalid age"}
function getCategoryByAge(age) { if (age >= 0 && age <= 12) return "Child" if (age >= 13 && age <= 19) return "Teenager" if (age >= 20 && age <= 35) return "Young Adult" if (age >= 36 && age <= 55) return "Adult" if (age > 55) return "Senior" return "Invalid age" }
советует Скопировано
🛠 Обязательно ставьте break
в конце каждого кейса. Такой код будет хорошо читаться и не приведёт к неожиданным багам.
🛠 Всегда добавляйте default
блок к своим свитчам. Код приложения постоянно меняется. Когда-нибудь свитч перестанет покрывать все возможные значения переменной и default
-случай будет вашей страховкой, которая не даст приложению разломаться.
🛠 Если в вашем свитче меньше трёх кейсов, то if
будет читаться проще.
🛠 Если внутри кейса нужно создать переменную, то придётся добавить фигурные скобки, иначе JavaScript упадёт с ошибкой:
switch (variable) { case 5: { const myVar = 'Hello' }}
switch (variable) { case 5: { const myVar = 'Hello' } }