Тернарный оператор и конструкция SwitchCase

Кратко о тернарных операторах

Тернарный оператор работает с тремя операндами: одним условием и двумя выражениями. Возвращает первое выражение, если условие истинно и второе, если условие ложно.

Используется как компактная замена условного оператора if...else.

Пример

const num = 5 console.log(num === 5 ? 'Пять' : 'Не пять') // Пять

Как пишется

(A) ? (B) : (C)

Где A — условие, B — первое выражение, C — второе выражение.

Если первый операнд A вычисляется в истинное выражение true, то оператор вернёт выражение B. Если в false — вернёт выражение C.

Как понять

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

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

const num = 10 
let result  if (num > 10) {   
	result = 'Число больше 10' 
} else {   
	result = 'Число меньше или равно 10' 
}  
 
console.log(result)`

Заменим условную конструкцию тернарным оператором:

const num = 10 
const result = num > 10 ? 'Число больше 10' : 'Число меньше или равно 10' 
 
console.log(result)`

Код сократился и стал устанавливать значение переменной num сразу при объявлении. Это позволило использовать const вместо let.

Тернарный оператор как выражение

Тернарный оператор возвращает результат, его можно записать в переменную, как в примере выше, или вернуть с помощью return из функции:

const salutation = function(name) {   
	return name ? `Рад видеть, ${name}!` : 'Привет, друг!' 
}  
 
console.log(salutation('Дока Дог')) // 'Рад видеть, Дока Дог!
 
console.log(salutation()) // 'Привет, друг!'``

Так как результат работы тернарного оператора можно записать в переменную, то смело делаем вывод, тернарный оператор — выражение.

Подробнее о разнице между выражениями и инструкциями читайте в отдельной статье.

Вложенные тернарные операторы

Внутри одного тернарного оператора можно написать другой:

const num = 10 
const result =  num > 10 ? 'Число больше 10' : 
	num === 10 ? 'Число равно 10' : 'Число меньше 10' 
	
console.log(result) // 'Число равно 10'`

В этом случае запись идентична использованию конструкций if...else if ... else. Сначала проверяется первое условие, если оно ложно, то проверяется второе и так далее. Отступы в примере проставлены для лучшей читаемости конструкции, они не влияют на выполнение кода.

На практике

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

Разберём выбор между тернарным оператором и if...else на примерах.

Допустим, нужно по-разному поприветствовать нового и уже зарегистрированного пользователя. Здесь удобно использовать тернарный оператор, так как проверка короткая:

const greetings = function(isRegistered, userName) {   
	return isRegistered ? `Привет, ${userName}!` : 'Привет, незнакомец' 
}

Когда появляются вложенные тернарные операторы, лучше переходить на if...else. Сравните код с тернарным оператором:

const greetings = function(isRegistered, userName, bePolite) {  
	return isRegistered ? `Привет, ${userName}!` : bePolite ? 'Здравствуйте!' : 'Привет, незнакомец' }``

И код с if...else:

const greetings = function(isRegistered, userName, bePolite) {   
	if (isRegistered) {     
		return `Привет, ${userName}!`   
	} else if (bePolite) {     
		return 'Здравствуйте!'   
	} else {     
		return 'Привет, незнакомец'   
	} 
}

Если же приветствие зависит от роли, то цепочки вложенных тернарных операторов становятся нечитаемыми:

const greetings = function(role) {   
	return result = role === 'admin' ? 'Приветствую, босс' : role === 'moder' ? 'Приветствую, смотритель порядка' : role === 'user' ? 'Здравствуй, пользователь' : role === 'guest' ? 'Здравствуй, гость' : 'Привет, некто' 
}

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

const greetings = function(role) {     
	switch (role) {         
		case 'admin':             
			return 'Приветствую, босс'         
		case 'moder':             
			return 'Приветствую, смотритель порядка'         
		case 'user':             
			return 'Здравствуй, пользователь'         
		case 'guest':             
			return 'Здравствуй, гость'         
		default:             
			return 'Привет, некто'     
	} 
}

На собеседовании

Что значит слово «тернарный»?

Кратко о SwitchCase

Кратко

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

Похож на if...else, но решает более узкую задачу.

Как пишется

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 }`

Как понять

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

Среди этих задач есть особый подтип — когда нужно посмотреть на значение переменной и выполнить разный код, в зависимости от этого значения. Например, применить разную скидку для клиентов разного статуса — самым любимым клиентам дать скидку 25%, с картой лояльности — 10%, а обычным покупателям не дать ничего.

Такую задачу тоже можно решить с помощью if..else:

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 }`

Код выше работает, но выглядит избыточно — в нем очень много сравнений с использованием memberStatus. Конструкция switch решает такую задачу меньшим объёмом кода:

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.1 вместо 0.2.

На практике

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

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

🛠 Если в вашем свитче меньше трёх кейсов, то if...else будет читаться проще.

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

switch (variable) {   
	case 5: {     
		const myVar = 'Hello'   } }`