Условные конструкции: if, else, switch
Условные конструкции
if/elseиswitchуправляют потоком выполнения программы, выбирая ветку кода на основе булева условия или сравнения значения с набором вариантов.
Зачем нужно
Условные конструкции — основа любой программной логики. Знание когда предпочесть switch вместо if/else, как использовать тернарный оператор и ?? / || для кратких выражений делает код чище и выразительнее.
Где используется
- Бизнес-логика: проверка прав, состояний, ролей
- Валидация данных
- Роутинг: разные действия для разных URL
- Обработка ошибок: разные реакции на разные типы
if / else if / else
function getDiscount(user) {
if (!user) {
return 0;
} else if (user.isPremium && user.yearsActive > 3) {
return 0.3;
} else if (user.isPremium) {
return 0.2;
} else if (user.isNewUser) {
return 0.1;
} else {
return 0;
}
}
Ранний return вместо вложенного else
// Паттерн guard clause — избегаем вложенности
function processOrder(order) {
if (!order) return null;
if (!order.items.length) return { error: 'Корзина пуста' };
if (!order.user.isVerified) return { error: 'Пользователь не верифицирован' };
// основная логика — без else
return completeOrder(order);
}
switch
Удобен для сравнения одного значения с множеством вариантов:
function getDayName(day) {
switch (day) {
case 0: return 'Воскресенье';
case 1: return 'Понедельник';
case 2: return 'Вторник';
case 3: return 'Среда';
case 4: return 'Четверг';
case 5: return 'Пятница';
case 6: return 'Суббота';
default: return 'Неизвестный день';
}
}
// Группировка case (fall-through)
function isWeekend(day) {
switch (day) {
case 0: // воскресенье
case 6: // суббота
return true;
default:
return false;
}
}
Тернарный оператор
// Вместо простого if/else
const status = user.isActive ? 'активен' : 'неактивен';
// Встроен в строку
const greeting = `Привет, ${user.isAdmin ? 'администратор' : 'пользователь'}!`;
// Вложенный тернарный — только если читаемо
const role =
user.isAdmin ? 'admin' :
user.isModerator ? 'moderator' :
'user';
Логические операторы как условия
// || — возвращает первое truthy значение (или последнее)
const name = user.name || 'Аноним';
const port = process.env.PORT || 3000;
// ?? (nullish coalescing) — только null/undefined, не falsy
const count = user.count ?? 0; // 0 если count === null/undefined
// user.count || 0 даст 0 даже при count=0 — не то же самое!
// && — возвращает первое falsy или последнее значение
const admin = user.isAdmin && user.permissions; // permissions если isAdmin
// В JSX: { isLoading && <Spinner /> }
// ?. (optional chaining) — условный доступ
const city = user?.address?.city ?? 'Не указан';
Object lookup вместо switch
Для простых маппингов:
// Вместо switch с 10+ case
const ACTION_HANDLERS = {
'increment': (state) => ({ ...state, count: state.count + 1 }),
'decrement': (state) => ({ ...state, count: state.count - 1 }),
'reset': (state) => ({ ...state, count: 0 }),
};
function reducer(state, action) {
const handler = ACTION_HANDLERS[action.type];
return handler ? handler(state) : state;
}
Частые ошибки
1. Забытый break в switch (fall-through)
switch (x) {
case 1:
doA;
// Нет break — упадёт в case 2!
case 2:
doB; // выполнится при x=1 И x=2
break;
}
2. switch использует === (строгое сравнение)
const input = '1'; // строка из input.value
switch (input) {
case 1: // число, не строка — не совпадёт!
console.log('один');
break;
}
// Решение: явное приведение или сравнение строк
switch (Number(input)) {
case 1: console.log('один'); break;
}
3. Вложенные тернарные — нечитаемо
// Плохо:
const x = a ? b ? 1 : 2 : c ? 3 : 4;
// Хорошо: if/else или именованные переменные
let x;
if (a) x = b ? 1 : 2;
else x = c ? 3 : 4;