Логические операторы
В обычной речи мы постоянно соединяем условия: «если есть билет и паспорт», «если идёт дождь или снег». В программе для этого есть три логических оператора: && («и»), || («или») и ! («не»).
Каждый из них строит выражение — код, у которого есть значение: a + b, 42, вызов Math.floor(2.5). Со значениями true и false логические операторы работают как в логике. Выражение a && b даёт true, только когда оба значения равны true, а a || b — когда хотя бы одно. Но && и || принимают значения любого типа, и результат у них не обязательно boolean:
console.log(true && false, true || false, !true); // false true false
console.log("Ann" || "guest"); // Ann
console.log("" || "guest"); // guest
console.log(0 && "never"); // 0
console.log(false && true || true); // trueДавайте разберём, что напечаталось:
- Первая строка — обычная логика:
false true false. "Ann" || "guest"вернулAnn, само левое значение, а неtrue."" || "guest"вернулguest: пустую строку оператор пропустил.0 && "never"вернул0, и до"never"дело не дошло.- Последняя строка печатает
true; почему именно так, разберём ниже.
Оба оператора возвращают одно из двух значений, между которыми стоят.
Что возвращают && и ||
Чтобы выбрать, какое значение вернуть, && и || проверяют левое так, будто оно boolean. Ложными при такой проверке считаются ровно восемь значений:
false;0,-0и0n;- пустая строка
""; nullиundefined;NaN.
Минус ноль -0 получается, например, из -1 * 0, а 0n — это ноль типа bigint: на этот тип указывает буква n в конце. Все остальные значения истинные, например "guest" и 42.
Каждый оператор выбирает результат по-своему:
||возвращает левое значение, если оно истинное, а иначе правое;&&возвращает левое значение, если оно ложное, а иначе правое;!всегда даётboolean:!0даётtrue, а!"Ann"—false.
Оператор || удобно представить как бейдж гостя на входе. Гость назвал имя — пишем имя, не назвал — пишем «guest». А && похож на ряд турникетов: проход останавливается у первого закрытого, и результатом становится именно он.
Если открыты все турникеты, результатом становится последний: 5 && 1 даёт 1. На этом картинка заканчивается: настоящий турникет только пропускает или не пропускает, а && возвращает само значение.
Сначала &&, потом ||
В одном выражении && выполняется раньше ||, как * раньше +. Поэтому последняя строка первой программы читается как (false && true) || true:
false && trueдаётfalse;false || trueдаётtrue.
Скобки делают порядок явным: (a && b) || c. Ставьте их, когда в одном выражении встречаются оба оператора: так его легче читать.
Короткая схема
Если левого значения хватает для ответа, правое даже не вычисляется. Это называют вычислением по короткой схеме. С турникетами то же самое: если первый закрыт, ко второму никто не идёт. После истинного значения || не смотрит направо, и && не смотрит направо после ложного:
function loud() {
console.log("called");
return 1;
}
console.log(1 || loud()); // 1
const x = 0 || loud(); // called
console.log(x); // 1В строке 1 || loud() функция loud не запускается: слева от || уже стоит истинное 1. В строке 0 || loud() слева ложный 0, поэтому loud запускается: печатает called и возвращает 1, и это значение попадает в x.
У && всё зеркально: правую часть он вычисляет только после истинного левого значения. Пройдите программу ниже по шагам и следите, когда над рамкой script появляется рамка loud: только тогда правая часть действительно вычисляется.
1function loud() {2 console.log("called");3 return 1;4}5 6const a = 1 || loud();7console.log(a);8const b = 0 || loud();9console.log(b);10const c = 0 && loud();11console.log(c);12const d = 5 && loud();13console.log(d);
Слева истинное 1, поэтому || сразу возвращает его и не вызывает loud().
Этот вопрос часто задают на собеседовании: что возвращают && и || и вызовется ли функция справа. Ответ: оператор возвращает одно из двух значений, а правая часть вычисляется, только если левой не хватило для ответа.
Оператор ??
Оператор ?? похож на ||, но правое значение возвращает, только когда левое — null или undefined. Его называют оператором нулевого слияния. На бейдже гостя он напишет «guest», только если графы с именем нет совсем. Значения 0, "" и false — не null и не undefined, поэтому ?? их сохраняет:
console.log(0 || 10, 0 ?? 10); // 10 0
console.log(null ?? 10, undefined ?? 10); // 10 10
console.log(false ?? true); // falseРазберём по строкам:
0 || 10даёт10, потому что0ложный, а0 ?? 10оставляет0.nullиundefinedоператор??заменяет на10.false ?? trueдаётfalse: это настоящее значение, а не его отсутствие.
Смешивать ?? с || или && без скобок нельзя: такая строка — синтаксическая ошибка. Со скобками запись работает: (a || b) ?? c.
Частая ошибка
Значение по умолчанию задают через ||, хотя 0 — допустимое значение:
const volume = 0;
const shown = volume || 50; // ✗
console.log(shown); // 50Громкость 0 ложная, поэтому || заменил её на 50. Когда заменить нужно только отсутствующее значение, пишите volume ?? 50: результат будет 0.
Главное
||возвращает левое значение, если оно истинное, иначе правое;&&— левое, если оно ложное, иначе правое.- Правая часть вычисляется, только если левой не хватило для ответа: это короткая схема.
&&выполняется раньше||, а??смешивают с ними только через скобки.??заменяет толькоnullиundefined, а||— любое ложное значение, даже0и"".
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.