Операторы в JavaScript: сравнение, логика, современные

Содержание

О проверке кода. Примеры не запускались — в отличие от материалов по Node.js с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».

Операторы кажутся мелочью, но именно на них рождаются самые коварные баги JavaScript — приведение типов, NaN, «ложные» значения. Разберём то, что действительно важно.

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

0 == '';         // true  ❌ — приведение типов
0 == false;      // true  ❌
null == undefined; // true ❌
'1' == 1;        // true  ❌

0 === '';        // false ✅ — разные типы, не равны
0 === false;     // false ✅
'1' === 1;       // false ✅

== приводит типы перед сравнением — отсюда 0 == '' и '1' == 1, дающие true. Эти правила запутаны и почти всегда не то, что вы имели в виду.

Правило простое: всегда ===. Строгое сравнение проверяет и значение, и тип, без приведения. Единственное исключение, которое иногда оставляют, — x == null для проверки на null или undefined разом, но и то на любителя. Помните: для объектов даже === сравнивает по ссылке, а не по содержимому.

Логические && и || возвращают операнд

Главная неожиданность: в JavaScript && и || возвращают не true/false, а один из операндов.

'Аня' || 'гость';    // 'Аня'  — || вернул первый истинный
'' || 'гость';       // 'гость' — '' ложное, взяли второй
0 || 100;            // 100

'Аня' && 'привет';   // 'привет' — && вернул последний, все истинны
'' && 'привет';      // ''      — && вернул первый ложный
  • || возвращает первый истинный операнд (или последний, если все ложные) — классический способ дать значение по умолчанию;
  • && возвращает первый ложный (или последний, если все истинные) — используют для условного доступа.

Оба короткозамкнутые: a && b() не вызовет b(), если a ложное. На этом строят проверки: user && user.name.

?? — нулевое слияние

У || есть ловушка: он считает ложными 0, '', false. Для значений по умолчанию это часто неверно:

const count = 0;
count || 10;    // 10  ❌ — 0 ложный, но это валидное значение!
count ?? 10;    // 0   ✅ — ?? срабатывает только на null/undefined

?? возвращает правый операнд, только если левый — null или undefined. Ноль, пустая строка и false он пропускает как валидные значения. Это делает ?? правильным выбором для дефолтов, когда 0 или '' — нормальные данные, а не «пусто».

|| против ?? для значений по умолчанию

|| — первый истинный

Срабатывает на ЛЮБОМ ложном

  • 0 || 10 → 10 (0 потерян!)
  • '' || 'x' → ‘x’ (пустая строка потеряна)
  • false || true → true
  • Опасно, если 0/’’/false валидны

?? — только null/undefined

Срабатывает только на «нет значения»

  • 0 ?? 10 → 0 ✅
  • '' ?? 'x' → ’’ ✅
  • null ?? 10 → 10
  • Правильно для числовых/строковых дефолтов

?. — опциональная цепочка

const user = { name: 'Аня' };   // address нет

user.address.city;      // ❌ TypeError: cannot read 'city' of undefined
user?.address?.city;    // ✅ undefined — без ошибки

// работает и с методами, и с массивами
user.getEmail?.();      // вызовет, только если метод существует
data?.[0]?.id;          // безопасный доступ к элементу массива

?. останавливает обращение и возвращает undefined, если слева null или undefined — вместо падения с TypeError. Убирает громоздкие лесенки user && user.address && user.address.city. Частая связка с ??: user?.address?.city ?? 'не указан' — безопасно достать и подставить дефолт.

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

const access = age >= 18 ? 'разрешён' : 'запрещён';

// вложенный — читаемо только в меру
const grade = score >= 90 ? 'A' : score >= 70 ? 'B' : 'C';

Тернарный условие ? да : нет — это if/else как выражение, возвращающее значение. Его можно присвоить, вернуть из функции, вставить в шаблонную строку. Удобен для коротких выборов; для сложной логики лучше обычный if, а вложенные тернарники глубже двух уровней уже вредят читаемости.

Полезная мелочь: возведение в степень и присваивания

2 ** 10;           // 1024 — оператор степени вместо Math.pow

let x = 5;
x += 3;            // 8   — то же, что x = x + 3
x ??= 10;          // 8   — присвоить, только если x был null/undefined
let y;
y ??= 10;          // 10  — y был undefined

Операторы ** (степень), +=/-=/*= и логические присваивания ??=, ||=, &&= — синтаксический сахар, который делает код короче. x ??= 10 = «присвоить 10, только если x пустой» — удобно для ленивой инициализации.


Смежные темы: примитивы и ссылки — почему === для объектов особый; типы данных — что считается ложным; условия и циклы. Полный список — в уроках JavaScript.

Частые вопросы

Чем === отличается от ==?
=== сравнивает без приведения типов: разные типы всегда не равны. == сначала приводит типы, из-за чего 0 == ’’ и null == undefined дают true. В коде используют только ===, чтобы не ловить сюрпризы приведения.
Что делает оператор ??
Нулевое слияние возвращает правый операнд, только если левый null или undefined. В отличие от ||, он не срабатывает на 0, ’’ и false — поэтому подходит для значений по умолчанию, где ноль и пустая строка валидны.
Зачем нужна опциональная цепочка ?.
Оператор ?. безопасно обращается к свойству: user?.address?.city вернёт undefined, если user или address равны null/undefined, вместо ошибки ‘cannot read property’. Убирает громоздкие проверки на каждом уровне.
Как работают && и || с не-булевыми значениями?
Они возвращают один из операндов, а не true/false. || возвращает первый истинный, && — первый ложный (или последний, если все истинны). Это используют для значений по умолчанию и условного выполнения.
Что такое тернарный оператор?
Короткая запись if/else в виде выражения: условие ? значение_если_да : значение_если_нет. Возвращает значение, поэтому его можно присвоить переменной или вернуть из функции.