Логические операторы: ||, && и !

Сравнение отвечает на один вопрос: «пять больше трёх?». Но настоящие условия почти всегда составные: «пускаем, если есть билет или пригласительный», «скидка, если студент и сегодня вторник», «показать кнопку, если пользователь не залогинен». Одним сравнением такое не записать.

Для связок у языка есть три оператора: || – ИЛИ, && – И, ! – НЕ. Разберём их по одному.

Когда одной проверки мало

Составные условия собираются из простых проверок.

|| (ИЛИ)

a || b истинно, когда истинен хотя бы один операнд: билет ИЛИ пригласительный – проходите. Ложно оно только в одном случае – когда ложны оба:

or.jsjs
const hasTicket = false;const hasInvite = true;// true – хватило пригласительногоconsole.log(hasTicket || hasInvite);// false – оба операнда ложныconsole.log(false || false);
aba || b
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse
Таблица истинности ИЛИ: ложь – только когда ложны оба операнда.

&& (И)

a && b истинно, только когда истинны оба операнда: студент И вторник – скидка. Одно «нет» – и всё выражение ложно:

and.jsjs
const isStudent = true;const isTuesday = false;// false – вторник не наступилconsole.log(isStudent && isTuesday);const hasCard = true;// true – истинны обаconsole.log(isStudent && hasCard);
aba && b
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse
Таблица истинности И: истина – только когда истинны оба операнда.

Операнды – любые значения

Операнды не обязаны быть булевыми – слева и справа встают строки, числа, null, undefined. «Да» это или «нет», оператор решает сам, по списку falsy. Подставим такие значения в левый операнд и посмотрим, как это меняет ответ:

operands.jsjs
const age = 20;// true – строка это «да»console.log('Ира' && age >= 18);// true – пустая строка это «нет»console.log('' || age >= 18);// false – null «нет», и сравнение «нет»console.log(null || age >= 65);

! (НЕ)

!a – единственный унарный оператор из тройки: операнд у него один, справа. Работает он в два такта: сначала оценивает операнд как «да» или «нет», потом возвращает противоположное. Ответ ! – всегда булев, каким бы ни был операнд.

На булевом операнде это просто смена ответа, на любом другом – сперва оценка, потом переворот:

not.jsjs
const hasTicket = false;// true – hasTicket равен falseconsole.log(!hasTicket);console.log(!true);  // false// false – непустая строка это «да», ответ перевёрнутconsole.log(!'текст');// true – ноль это «нет»console.log(!0);// true – пустая строка это «нет»console.log(!'');
a!a
truefalse
falsetrue
Таблица истинности НЕ: ответ всегда переворачивается.

!! – приведение к boolean

Два знака подряд – не отдельный оператор, а !, применённый к результату !: запись !!x равносильна !(!x). Первым срабатывает правый знак, тот, что ближе к операнду: он оценивает x и возвращает противоположное булево. Второй знак переворачивает это булево обратно.

После двух переворотов оценка та же, что была, но уже в виде true или false – так значение любого типа приводят к boolean. Разберём по шагам:

Два знака: !!invite по шагам
const invite = 'VIP-77';
В invite лежит строка – не true и не false. Задача: получить из неё булев ответ «да/нет».
console.log(!!invite);
Консоль
Нет вывода в консоль.
double-not.jsjs
console.log(!!'текст');  // true// true – тот же ответconsole.log(Boolean('текст'));console.log(!!0);  // falseconsole.log(!!'');  // false// true – строка не пустаяconsole.log(!!'0');

Приоритет: место логики в выражении

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

Считается такое выражение не по порядку записи, а по ступеням приоритета – у логики в этой лестнице свои:

СтупеньОператорыЗаметка
1 – раньше всех( )скобки переигрывают любой порядок
2!унарное НЕ – выше всех бинарных операторов
3* / % + -арифметика – по своим внутренним ступеням
4> < >= <=отношения
5=== !==равенства – ступенью ниже отношений
6&&И – раньше ИЛИ
7 – позже всех||ИЛИ – последним

В true || false && false первым записан ||, а вычисляется первым && – его ступень выше. Нужен другой порядок – ставьте скобки:

priority.jsjs
// true – первым сработал &&console.log(true || false && false);// false – скобки переиграли порядокconsole.log((true || false) && false);

Соберём выражение сразу из нескольких ступеней и пройдём его по шагам:

Пять ступеней в одном выражении
const age = 20;
Возраст посетителя – 20.
const isBlocked = false;
const isVip = true;
console.log(age >= 6 + 12 && !isBlocked || isVip);
Консоль
Нет вывода в консоль.
Переменные
age = 20

Движок разобрал это выражение и без скобок – но человеку пришлось бы вспомнить таблицу. В настоящем коде смысловые группы часто выделяют скобками, даже когда порядок вычисления и без них правильный:

readable.jsjs
// работает, но читается по таблицеage >= 6 + 12 && !isBlocked || isVip;// та же логика – группы видны сразу(age >= 18 && !isBlocked) || isVip;

// теперь вы знаете

  1. || – «или», && – «и», ! – «не»; у каждого – своя таблица истинности
  2. Операнд любого типа оператор сам оценивает как «да» или «нет»; ! всегда возвращает булево, а !!x приводит значение к булеву
  3. Порядок ступеней: скобки, затем !, арифметика, сравнения, &&, последним ||
  4. || и && читают операнды слева направо и останавливаются, как только ответ определён

Проверьте себя

Посетителю 14 лет, билета нет: age >= 12 && hasTicket. Что вернёт выражение?

Что выведет console.log(!(5 > 3))? Впишите ответ словом.

Что вернёт true || false && false?

Кнопка доступна, если пользователь не заблокирован и при этом является администратором или редактором. Какое выражение это записывает?

переключают уроки · не работают при фокусе в полях ввода