Условные конструкции if в JavaScript и jQuery: синтаксис, тернарник, switch

Условные конструкции if в JavaScript и jQuery: синтаксис, тернарник, switch Полезное

Условная конструкция — это инструкция языка, которая выполняет один блок кода вместо другого в зависимости от того, истинно ли заданное условие. В JavaScript такими инструкциями служат if, if...else, цепочка else if, оператор switch и тернарный оператор ?:. В jQuery отдельных условных операторов нет: jQuery — это библиотека поверх JavaScript, и в ней используется тот же синтаксис условий. Разберем синтаксис по порядку, затем ключевую пару == против ===, правдивость значений (truthy/falsy) и то, как условия применяют к элементам страницы — сперва в стиле jQuery, потом на нативном JavaScript.

Сразу разведем два понятия. jQuery — внешняя библиотека (актуальная стабильная ветка 3.7.x, 2023 год), которую подключают к странице отдельно. Нативный JavaScript — сам язык, встроенный в браузер, ему подключение не нужно. Условия пишутся одинаково; разница только в том, как найти элемент страницы и прочитать его состояние.

Оператор if: минимальный рабочий пример

Начнем с законченного примера, который можно скопировать в консоль браузера (клавиша F12, вкладка Console) и запустить.

let temperature = 25;

if (temperature > 20) {
  console.log("Тепло, куртка не нужна");
}
// В консоли: Тепло, куртка не нужна

Оператор начинается с ключевого слова if, за ним в круглых скобках идет условие, а в фигурных скобках — блок инструкций. Блок выполняется, если условие приводится к true. Здесь temperature > 20 дает true, поэтому строка выводится. Если бы переменная равнялась 15, условие дало бы false и консоль осталась бы пустой.

Фигурные скобки можно опустить только для одной инструкции: if (x > 0) console.log(x);. Но ставить их лучше всегда — так при дописывании второй строки в блок не появится скрытая ошибка.

if…else и цепочка else if

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

let score = 75;

if (score >= 90) {
  console.log("Отлично");
} else if (score >= 70) {
  console.log("Хорошо");
} else if (score >= 50) {
  console.log("Удовлетворительно");
} else {
  console.log("Пересдача");
}
// В консоли: Хорошо

Проверки идут сверху вниз. Первое условие score >= 90 ложно, поэтому управление уходит к score >= 70 — оно истинно, выполняется его блок, а остальные ветки уже не проверяются. Финальный else без условия срабатывает, только если все проверки выше оказались ложными. Порядок веток важен: если бы score >= 50 стояло первым, оно перехватило бы и значение 75, и вывод был бы неверным.

Выполняется ровно один блок из цепочки — тот, чье условие первым дало true, либо else, если ни одно не дало.

Правдивость значений: truthy и falsy

В условии не обязательно писать сравнение. JavaScript приводит любое значение к логическому типу. Значений, которые приводятся к false, всего восемь, их называют falsy:

if (false) {}      // falsy
if (0) {}          // falsy: ноль
if (-0) {}         // falsy: минус ноль
if (0n) {}         // falsy: ноль типа BigInt
if ("") {}         // falsy: пустая строка
if (null) {}       // falsy
if (undefined) {}  // falsy
if (NaN) {}        // falsy: "не число"

Все остальное приводится к true и называется truthy. Здесь интуиция подводит: строки "0" и "false" непустые, а значит truthy; пустой массив [] и пустой объект {} тоже truthy.

let items = [];
if (items) {
  console.log("Массив есть как объект");
}
// В консоли: Массив есть как объект (пустой массив - truthy!)

if (items.length) {
  console.log("В массиве есть элементы");
}
// Ничего не выводится: length равен 0, а 0 - falsy

Отсюда правило: непустоту массива проверяют не по нему самому, а по length. Проверка «значение задано» через truthy опасна: if (name) отсечет и undefined, и валидную пустую строку, и число 0. Чтобы поймать именно null или undefined, сравнивают явно: if (value != null) — единственный корректный случай нестрогого !=, он ловит сразу оба.

Сравнение == и ===: строгое против нестрогого

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

  • === — строгое равенство: сравнивает и значение, и тип, приведения типов не делает.
  • == — нестрогое равенство: перед сравнением приводит операнды к общему типу по неочевидным правилам.
Выражение Результат Почему
5 === 5 true одинаковый тип и значение
5 === "5" false число против строки, типы разные
5 == "5" true строка приведена к числу
0 == "" true оба приведены к числу 0
0 == false true false приведен к 0
null == undefined true спецправило языка
null === undefined false типы разные
NaN === NaN false NaN не равен ничему, включая себя

Правило простое: по умолчанию используйте === и !==. Нестрогое == включает цепочку приведений, которую трудно держать в голове, и порождает баги вроде 0 == "" -> true. Единственное оправданное исключение — проверка x == null для одновременного отлова null и undefined.

Отдельная частая ошибка — перепутать сравнение с присваиванием:

let x = 5;
if (x = 0) {          // одиночное = это присваивание, не сравнение
  console.log("ноль");
}
// Ничего не выводится: x стал 0, условие получило 0 (falsy)

Здесь x = 0 присваивает ноль и возвращает его; ноль falsy, блок пропущен, а переменная незаметно испорчена. Правильно — двойной или тройной знак:

if (x === 0) {
  console.log("ноль");
}

Логические операторы

Условия объединяют тремя операторами: && (И), || (ИЛИ), ! (НЕ).

let age = 20;
let hasTicket = true;

if (age >= 18 && hasTicket) {
  console.log("Проход разрешен");
}
// В консоли: Проход разрешен

if (age < 18 || !hasTicket) {
  console.log("Проход запрещен");
}
// Ничего не выводится: оба условия ложны

Операторы && и || работают с сокращением вычислений: && останавливается на первом falsy-операнде, || — на первом truthy. При этом они возвращают не строго true/false, а сам операнд, на котором остановились. Это используют для значений по умолчанию, но с оговоркой:

let input = "";
let name1 = input || "Гость";   // "" falsy -> name1 станет "Гость"
console.log(name1);             // В консоли: Гость

let count = 0;
let shown = count ?? 100;       // ?? срабатывает только на null/undefined
console.log(shown);             // В консоли: 0

Тут важна граница: || подставит запасное значение на любом falsy, включая валидные 0 и "". Если запасное нужно только для null и undefined, берут оператор ?? (nullish coalescing) — как в примере с count, где ноль сохраняется, а не заменяется на 100.

Тернарный оператор

Тернарный оператор ?: — это не инструкция, а выражение: он возвращает значение, поэтому его можно присвоить переменной. Форма: условие ? значение_если_true : значение_если_false.

let hour = 14;
let greeting = hour < 12 ? "Доброе утро" : "Добрый день";
console.log(greeting);
// В консоли: Добрый день

Тернарник уместен, когда по условию нужно выбрать одно из двух значений. Для ветвления с побочными действиями (вывод в консоль, вызовы функций) читаемее обычный if. Вложенные тернарники (a ? b : c ? d : e) быстро становятся нечитаемыми — для трех и более исходов берут if...else if или switch.

Оператор switch

switch выбирает блок по значению одного выражения. Сравнение веток case идет по строгому равенству (как ===), приведения типов не будет.

let day = 3;

switch (day) {
  case 1:
    console.log("Понедельник");
    break;
  case 3:
    console.log("Среда");
    break;
  case 6:
  case 7:
    console.log("Выходной");
    break;
  default:
    console.log("Обычный день");
}
// В консоли: Среда

Слово break завершает switch и передает управление коду после него. Без break выполнение «проваливается» в следующий case — иногда это делают намеренно (ветки case 6 и case 7 выше делят один блок), но чаще пропущенный break — это баг. Ветка default необязательна и срабатывает, если ни один case не совпал; по смыслу это else. Поскольку switch сравнивает строго, switch (day) с day = "3" (строка) не попадет в case 3 (число).

Условия в jQuery и нативный аналог

jQuery считается legacy: новые проекты чаще пишут на нативном JavaScript или фреймворках, где ручной работы с DOM почти нет. Но jQuery еще встречается в поддержке старых сайтов, поэтому полезно видеть обе записи рядом. Сами условия (if, switch, тернарник) в jQuery те же — меняется только способ найти элемент и прочитать его состояние.

Типичная задача: показать блок, если на странице есть элемент с определенным классом.

// Вариант на jQuery
if ($(".promo").length > 0) {
  $(".banner").show();
} else {
  $(".banner").hide();
}
// Тот же смысл на нативном JavaScript
const banner = document.querySelector(".banner");
if (document.querySelector(".promo")) {
  banner.style.display = "";     // показать
} else {
  banner.style.display = "none"; // скрыть
}

Ключевой момент про jQuery: выражение $(".promo") всегда возвращает объект-коллекцию, и этот объект truthy даже когда ничего не найдено. Поэтому проверяют не сам объект, а .length — число найденных элементов. У нативного querySelector иначе: он возвращает сам элемент или null, если ничего не нашлось, и null falsy, так что его можно проверять прямо в if.

Соответствие частых проверок:

Задача jQuery Нативный JavaScript
Элемент найден $(sel).length > 0 document.querySelector(sel) !== null
Есть класс $(el).hasClass("active") el.classList.contains("active")
Подходит под селектор $(el).is(".active") el.matches(".active")
Отмечен чекбокс $(el).is(":checked") el.checked
Добавить/убрать класс $(el).toggleClass("open") el.classList.toggle("open")

Пример с проверкой класса и метода is():

const el = document.querySelector(".menu");

// jQuery: $(el).is(".open")
// Нативно:
if (el.classList.contains("open")) {
  el.classList.remove("open");
  console.log("Меню закрыто");
} else {
  el.classList.add("open");
  console.log("Меню открыто");
}

Оговорим границу проверки видимости. В jQuery есть селектор $(el).is(":visible"), у которого нет одной короткой нативной замены: видимость зависит от display, размеров и положения элемента. Грубый нативный признак «элемент вообще отрисован» — el.offsetParent !== null, но он не учитывает visibility: hidden и position: fixed. В современных браузерах для этого появился метод el.checkVisibility(); его поддержку под нужные браузеры стоит проверять отдельно.

Выводы

  • Условные конструкции JavaScript — это if, if...else, цепочка else if, тернарный оператор ?: и switch; в jQuery собственных условий нет, используется тот же синтаксис языка.
  • По умолчанию сравнивайте через === и !==: нестрогое == делает неочевидные приведения типов (0 == "" дает true); оправданное исключение — только x == null.
  • В условии значение приводится к логическому типу: falsy-значений восемь (false, 0, -0, 0n, "", null, undefined, NaN), все прочее truthy; пустой массив и пустая строка "0" — truthy.
  • switch сравнивает ветки case строго и требует break, иначе выполнение проваливается в следующую ветку; тернарник возвращает значение и хорош для выбора из двух вариантов.
  • jQuery — legacy: $(sel).length, hasClass, is() имеют прямые нативные аналоги querySelector, classList.contains, matches; для новых проектов берите нативный JavaScript.

Где применяется / связь с практикой

Условия — это основа любой логики в браузере: показать или скрыть блок, проверить форму перед отправкой, выбрать текст по роли пользователя, разветвить обработчик клика. Ошибки в них (перепутанные == и ===, забытый break, проверка truthy вместо .length) дают самые незаметные баги — код работает на одних данных и молча ломается на других, поэтому важно понимать правила приведения, а не подбирать знаки наугад.

Освойте тему на практике

Разобрать это на практике — с живой отладкой в консоли, разбором DOM и переходом от jQuery к нативному коду — удобнее под руководством. На курсе JavaScript Basic в Otus условные конструкции, приведение типов и работа с DOM идут по шагам с проверкой в браузере. Посмотреть формат и темы вживую можно на открытых уроках Otus — там разбирают конкретные задачи и отвечают на вопросы.

FAQ

Можно ли писать if без фигурных скобок?
Да, но только для одной инструкции: if (x > 0) doSomething();. Как только в блоке появляется вторая строка, ей нужны скобки, иначе она выполнится вне условия. Практика — ставить скобки всегда, чтобы не поймать эту ошибку при дописывании кода.

Чем тернарный оператор отличается от if?
Тернарник — это выражение: он возвращает значение и его можно присвоить переменной (let x = a ? b : c). Обычный if — инструкция, значения не возвращает. Тернарник берут для выбора одного из двух значений, if — для ветвления с действиями.

Почему условие срабатывает не так, как я ожидал, при сравнении разных типов?
Скорее всего использовано нестрогое ==, которое приводит операнды к общему типу перед сравнением, и получается, например, 0 == "" -> true. Замените на строгое ===, которое учитывает и тип, и значение, — неожиданных совпадений станет меньше.

OTUS Журнал
Бесплатные открытые уроки (поп-ап)