В JavaScript існує чотири логічні оператори: ||
(АБО), &&
(І), !
(НЕ), ??
(оператор null-об’єднання). В цьому розділі ми розглянемо перші три оператори, а оператор ??
— в наступному розділі.
Хоча вони називаються “логічними”, вони можуть бути застосовані до значень будь-якого типу, не тільки булевих. Їх результати також можуть бути будь-якого типу.
Подивимось більш детально.
|| (АБО)
Оператор “АБО” представлений двома символами вертикальної лінії:
result = a || b;
У класичному програмуванні логічний оператор АБО призначений для маніпулювання лише булевими значеннями. Якщо будь-який з його аргументів означає true
, повертається true
, інакше повертається false
.
У JavaScript цей оператор складніший і потужніший. Але спочатку подивимося, що відбувається з булевими значеннями.
Є чотири можливі логічні комбінації:
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
Як бачимо, результат завжди true
, за винятком випадку, коли обидва операнди false
.
Якщо операнд не є булевим, він перетворюється на булевий для обчислення.
Наприклад, число 1
розглядається як true
, число 0
— як false
:
if (1 || 0) { // працює так само, як ( true || false )
alert( 'правдиво!' );
}
У більшості випадків АБО ||
використовується в інструкціях if
, щоб перевірити, чи є будь-яка із заданих умов true
.
Наприклад:
let hour = 9;
if (hour < 10 || hour > 18) {
alert( 'Офіс зачинений.' );
}
Ми можемо передавати більше умов:
let hour = 12;
let isWeekend = true;
if (hour < 10 || hour > 18 || isWeekend) {
alert( 'Офіс зачинений.' ); // це вихідні
}
АБО "||" знаходить перше правдиве значення
Описана вище логіка дещо класична. Тепер введімо “додаткові” особливості JavaScript.
Розширений алгоритм працює наступним чином.
Дано кілька значень, розділених оператором АБО:
result = value1 || value2 || value3;
Оператор АБО ||
робить наступне:
- Обчислює операнди зліва направо.
- Перетворює значення кожного операнда на булеве. Якщо результат
true
, зупиняється і повертає початкове значення цього операнда. - Якщо всі операнди були обчисленні (тобто усі були
false
), повертає останній операнд.
Значення повертається у первісному вигляді без конвертації.
Іншими словами, ланцюжок з АБО ||
повертає перше правдиве значення або останнє, якщо правдивого значення не знайдено.
Наприклад:
alert( 1 || 0 ); // 1 (1 є правдивим)
alert( null || 1 ); // 1 (1 є першим правдивим значенням)
alert( null || 0 || 1 ); // 1 (перше правдиве значення)
alert( undefined || null || 0 ); // 0 (усі хибні, повертається останнє значення)
Це призводить до цікавого використання, у порівнянні з “чистим, класичним, виключно-булевим АБО”.
-
Отримання першого істинного значення зі списку змінних або виразів.
Наприклад, маємо змінні
firstName
,lastName
таnickName
, усі необов’язкові (тобто вони можуть бути невизначеними або мати хибні значення).Використаємо АБО
||
, щоб вибрати ту змінну, яка має дані, і виведемо її (або рядок"Анонім"
, якщо жодна змінна не має даних):let firstName = ""; let lastName = ""; let nickName = "СуперКодер"; alert( firstName || lastName || nickName || "Анонім"); // СуперКодер
Якщо всі змінні мали б порожні рядки, тоді показалося слово
"Анонім"
. -
Обчислення короткого замикання.
Іншою особливістю оператора АБО
||
є так зване “обчислення короткого замикання”.Це означає, що оператор
||
опрацьовує аргументи доти, доки не досягається перше правдиве значення, після чого це значення негайно повертається, без подальшого опрацювання решти аргументів.Важливість такої особливості стає очевидною, якщо операнд є не просто змінною, а виразом із побічним ефектом, як-от присвоєння змінної або виклик функції.
У наведеному нижче прикладі виведеться лише друге повідомлення:
true || alert("не виведеться"); false || alert("виведеться");
В першому рядку оператор АБО
||
зупиняє виконання відразу після того, як “побачить” що лівий вираз єtrue
, тожalert
не виконається.Деколи таку конструкцію використовують, щоб виконувати команди лише при хибності умови ліворуч від оператора.
&& (І)
Оператор І представлений двома амперсандами &&
:
result = a && b;
У класичному програмуванні І повертає true
, якщо обидва оператори є правдивими, і false
в іншому випадку:
alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false
Приклад з if
:
let hour = 12;
let minute = 30;
if (hour == 12 && minute == 30) {
alert( 'Час: 12:30' );
}
Так само як з АБО, будь-яке значення дозволено як операнд І:
if (1 && 0) { // обчислюється як true && false
alert( "не буде працювати, тому що результат хибний" );
}
І “&&” шукає перше хибне значення
Дано декілька значень, об’єднаних кількома І:
result = value1 && value2 && value3;
Оператор І &&
робить наступне:
- Обчислює операнди зліва направо.
- Перетворює кожен операнд на булевий. Якщо результат
false
, зупиняється і повертає оригінальне значення того операнда. - Якщо всі операнди були обчисленні (тобто усі були правдиві), повертає останній операнд.
Іншими словами, І повертає перше хибне значення, або останнє значення, якщо жодного хибного не було знайдено.
Правила, наведені вище, подібні до правил АБО. Різниця полягає в тому, що І повертає перше хибне значення, тоді як АБО повертає перше правдиве.
Приклади:
// якщо перший операнд правдивий,
// І повертає другий операнд:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5
// якщо перший операнд хибний,
// І повертає саме його. Другий операнд ігнорується
alert( null && 5 ); // null
alert( 0 && "неважливо" ); // 0
Ми також можемо передавати декілька значень поспіль. Подивіться, як повертається перше хибне:
alert( 1 && 2 && null && 3 ); // null
Коли всі значення є правдивими, повертається останнє значення:
alert( 1 && 2 && 3 ); // 3, останнє
&&
вище за АБО ||
Оператор І &&
має вищий пріоритет за АБО ||
.
Отже, код a && b || c && d
по суті є таким самим, як код з виразами &&
у дужках: (a && b) || (c && d)
.
if
на ||
чи &&
Деколи оператор І &&
використовують як “скорочений варіант if
”.
Наприклад:
let x = 1;
(x > 0) && alert( 'Більше за нуль!' );
Дія у правій частині &&
буде виконуватися, тільки якщо обчислення дійде до неї. Тобто тільки якщо (x > 0)
є істинним.
Тому, власне, ми маємо аналог для:
let x = 1;
if (x > 0) alert( 'Більше за нуль!' );
Хоча варіант з &&
видається коротшим, конструкція з if
є більш очевидною і зазвичай більш читабельною. Тому ми рекомендуємо використовувати кожну конструкцію за своїм призначенням: використовуємо if
, якщо нам потрібна інструкція if
, і використовуємо &&
, якщо нам потрібен оператор І.
! (НЕ)
Булевий оператор НЕ представлений знаком оклику !
.
Синтаксис дуже простий:
result = !value;
Оператор приймає один аргумент і виконує наступне:
- Перетворює операнд на булевий тип:
true/false
. - Повертає зворотне значення.
Наприклад:
alert( !true ); // false
alert( !0 ); // true
Подвійний НЕ !!
іноді використовується для перетворення значення на булевий тип:
alert( !!"не пустий рядок" ); // true
alert( !!null ); // false
Тобто, перший НЕ перетворює значення на булеве і повертає зворотне, а другий НЕ інвертує його знову. Зрештою ми маємо просте перетворення значень на булевий тип.
Є трохи довший спосіб зробити те ж саме – вбудована функція Boolean
:
alert( Boolean("не пустий рядок") ); // true
alert( Boolean(null) ); // false
Пріоритет НЕ !
є найвищим серед усіх логічних операторів, тому він завжди виконується першим, перед &&
або ||
.