21 вересня 2023 р.

Логічні оператори

В 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 (усі хибні, повертається останнє значення)

Це призводить до цікавого використання, у порівнянні з “чистим, класичним, виключно-булевим АБО”.

  1. Отримання першого істинного значення зі списку змінних або виразів.

    Наприклад, маємо змінні firstName, lastName та nickName, усі необов’язкові (тобто вони можуть бути невизначеними або мати хибні значення).

    Використаємо АБО ||, щоб вибрати ту змінну, яка має дані, і виведемо її (або рядок "Анонім", якщо жодна змінна не має даних):

    let firstName = "";
    let lastName = "";
    let nickName = "СуперКодер";
    
    alert( firstName || lastName || nickName || "Анонім"); // СуперКодер

    Якщо всі змінні мали б порожні рядки, тоді показалося слово "Анонім".

  2. Обчислення короткого замикання.

    Іншою особливістю оператора АБО || є так зване “обчислення короткого замикання”.

    Це означає, що оператор || опрацьовує аргументи доти, доки не досягається перше правдиве значення, після чого це значення негайно повертається, без подальшого опрацювання решти аргументів.

    Важливість такої особливості стає очевидною, якщо операнд є не просто змінною, а виразом із побічним ефектом, як-от присвоєння змінної або виклик функції.

    У наведеному нижче прикладі виведеться лише друге повідомлення:

    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' );
}

Так само як з АБО, будь-яке значення дозволено як операнд І: