Логические операторы: ||, && и !
Сравнение отвечает на один вопрос: «пять больше трёх?». Но настоящие условия почти всегда составные: «пускаем, если есть билет или пригласительный», «скидка, если студент и сегодня вторник», «показать кнопку, если пользователь не залогинен». Одним сравнением такое не записать.
Для связок у языка есть три оператора: || – ИЛИ, && – И, ! – НЕ. Разберём их по одному.
|| (ИЛИ)
a || b истинно, когда истинен хотя бы один операнд: билет ИЛИ пригласительный – проходите. Ложно оно только в одном случае – когда ложны оба:
const hasTicket = false;const hasInvite = true;// true – хватило пригласительногоconsole.log(hasTicket || hasInvite);// false – оба операнда ложныconsole.log(false || false);a | b | a || b |
|---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
&& (И)
a && b истинно, только когда истинны оба операнда: студент И вторник – скидка. Одно «нет» – и всё выражение ложно:
const isStudent = true;const isTuesday = false;// false – вторник не наступилconsole.log(isStudent && isTuesday);const hasCard = true;// true – истинны обаconsole.log(isStudent && hasCard);a | b | a && b |
|---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
Операнды – любые значения
Операнды не обязаны быть булевыми – слева и справа встают строки, числа, null, undefined. «Да» это или «нет», оператор решает сам, по списку falsy. Подставим такие значения в левый операнд и посмотрим, как это меняет ответ:
const age = 20;// true – строка это «да»console.log('Ира' && age >= 18);// true – пустая строка это «нет»console.log('' || age >= 18);// false – null «нет», и сравнение «нет»console.log(null || age >= 65);! (НЕ)
!a – единственный унарный оператор из тройки: операнд у него один, справа. Работает он в два такта: сначала оценивает операнд как «да» или «нет», потом возвращает противоположное. Ответ ! – всегда булев, каким бы ни был операнд.
На булевом операнде это просто смена ответа, на любом другом – сперва оценка, потом переворот:
const hasTicket = false;// true – hasTicket равен falseconsole.log(!hasTicket);console.log(!true); // false// false – непустая строка это «да», ответ перевёрнутconsole.log(!'текст');// true – ноль это «нет»console.log(!0);// true – пустая строка это «нет»console.log(!'');a | !a |
|---|---|
true | false |
false | true |
!! – приведение к boolean
Два знака подряд – не отдельный оператор, а !, применённый к результату !: запись !!x равносильна !(!x). Первым срабатывает правый знак, тот, что ближе к операнду: он оценивает x и возвращает противоположное булево. Второй знак переворачивает это булево обратно.
После двух переворотов оценка та же, что была, но уже в виде true или false – так значение любого типа приводят к boolean. Разберём по шагам:
invite лежит строка – не true и не false. Задача: получить из неё булев ответ «да/нет».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 первым записан ||, а вычисляется первым && – его ступень выше. Нужен другой порядок – ставьте скобки:
// true – первым сработал &&console.log(true || false && false);// false – скобки переиграли порядокconsole.log((true || false) && false);Соберём выражение сразу из нескольких ступеней и пройдём его по шагам:
20.Движок разобрал это выражение и без скобок – но человеку пришлось бы вспомнить таблицу. В настоящем коде смысловые группы часто выделяют скобками, даже когда порядок вычисления и без них правильный:
// работает, но читается по таблицеage >= 6 + 12 && !isBlocked || isVip;// та же логика – группы видны сразу(age >= 18 && !isBlocked) || isVip;// теперь вы знаете
||– «или»,&&– «и»,!– «не»; у каждого – своя таблица истинности- Операнд любого типа оператор сам оценивает как «да» или «нет»; ! всегда возвращает булево, а !!x приводит значение к булеву
- Порядок ступеней: скобки, затем
!, арифметика, сравнения,&&, последним|| ||и&&читают операнды слева направо и останавливаются, как только ответ определён
Посетителю 14 лет, билета нет: age >= 12 && hasTicket. Что вернёт выражение?
Что выведет console.log(!(5 > 3))? Впишите ответ словом.
Что вернёт true || false && false?
Кнопка доступна, если пользователь не заблокирован и при этом является администратором или редактором. Какое выражение это записывает?