Kot Źródłowy

Prawda czy fałsz – czyli co wpisać w if-a

Cześć! Jeśli już tu trafiłeś, to znaczy, że zaciekawił cię ten, z pozoru trywialny, temat. Albo chcesz się pośmiać, bo wiesz, że nic cię już nie zaskoczy. Stawiam jednak, że to ta pierwsza opcja, gdyż wolę być optymistką. Jednocześnie zakładam, że niejeden raz już pisałeś coś w stylu zaprezentowanym poniżej:

if (odpowiednieWarunki()) {
	// dziejące się rzeczy
}

Właśnie dzisiaj zajmiemy się wszystkim, co wiąże się z warunkami w JS. No, może prawie wszystkim, bo uważam, że dogłębne omówienie tematu logiki, działań logicznych, ich przedstawieniu w językach programowania, to może być ciekawy temat na serię wykładów, a nie tylko krótki wpis na blogu. Temat wartości i działań logicznych, jak wszystko w tym języku, wygląda na pierwszy rzut oka co najmniej dziwnie. Mam jednak wrażenie, że po przeczytaniu tego wpisu wszystko okaże się w pełni jasne i klarowne. A jeśli podoba ci się coś na tym blogu lub dowiedziałeś się czegoś nowego, to zapraszam na mojego Facebooka.

Truthy i falsy values

Zacznijmy od podstaw, żeby była jasność w temacie. Wiemy doskonale, że JS jest językiem dynamicznie typowanym, co sprawia, że silnik sam mapuje nam jedne wartości na inne. To znaczy, że każda wartość ma swój odpowiednik w wartości innego typu. Chcesz przykładu? U mnie zawsze. Mamy sobie liczby, mogą one być konwertowane na łańcuchy znaków. Widać to doskonale na tym przykładzie:

let a = 5;
let b = a + '3';
console.log(b); //53
console.log(typeof b) //string

A jak to jest przy konwertowaniu czegokolwiek na wartości logiczne? No oczywiście, część wartości zostaje true, a część false. I właśnie tu z pomocą przychodzą nam tzw. falsy values, czyli lista rzeczy, dzięki którym otrzymamy false:

  • null;
  • NaN;
  • 0;
  • empty string (“” or ‘’ or ``);
  • undefined

Warto je zapamiętać, żeby potem nie było niespodzianek przy sprawdzaniu warunku. Pozostałe wartości dadzą nam true, co szczególnie nie powinno nikogo dziwić. Zauważ jedynie, że zarówno pusty obiekt {}, jak i pusta tablica [] zawsze dadzą nam true. W ogóle to obiekty zawsze dadzą nam true, więc niepolecane new Boolean(false) też.

Operatory logiczne

Z poprzedniej sekcji tego artykułu wiemy już, jakie wartości dają nam przy konwertowaniu na typ logiczny true a jakie false. Ta wiedza przyda nam się teraz w szczególności. Będziemy się bawić operatorami logicznymi. W JS mamy trzy takie:

  • && jako logiczne AND
  • || jako logiczne OR
  • ! jako zaprzeczenie, czyli NOT

Najprościej jest zacząć od końca, bo zaprzeczenie z prawdy robi fałsz i odwrotnie. Jak to działa dla innych wartości? Najpierw są konwertowane na wartości logiczne, a potem to już wiecie. Zabawne jest to, że tego operatora możemy użyć podwójnie, co pozwala uzyskać wartość logiczną odpowiadającą danej wartości.

!! 1; // true

Pozostałe dwa operatory potrzebują dwóch wartości obok siebie, aby przeprowadzić na nich działanie logiczne.

Logiczne AND

Jak zapewne wiesz, to w logice wynik tego działania jest prawdą tylko wtedy, gdy oba jego człony są prawdziwe. W każdym innym przypadku daje nam fałsz. Służy do połączenia dwóch prostszych działań logicznych. Takim przykładem, który mi przychodzi do głowy, jest moment, w którym walidujesz hasło użytkownika. Załóżmy, że na twojej stronie hasło ma być dłuższe niż 8 znaków i krótsze niż 25. W JS kod takiego rozwiązania miałby następującą postać:

function checkPasswordLength(passphrase) {
	return passphrase.length > 8 && passphrase.length < 25;
}

Ciekawe jest tutaj, co taki JS wtedy robi. Kiedy mamy do czynienia z tym działaniem silnik JS-a sobie rozdziela takie działanie na dwie części A.passphrase.length > 8 i B.passphrase.length < 25. Algorytm postępowania wygląda następująco:

  1. Sprawdź, czy pierwszy element (A.) można skonwertować do wartości true.
  2. Jeżeli tak, to zwróć drugi element (B.).
  3. Jeżeli nie, to zwróć pierwszy element (A.).

To może wydawać się dziwne, ale tak naprawdę ma dużo sensu. No bo zastanów się, && zwraca prawdę tylko i wyłącznie wtedy, kiedy oba człony są prawdą. Więc jeśli przeanalizujesz pod tym kątem pierwszy i on zwróci prawdę, to musimy sprawdzić jeszcze drugi i to właśnie od niego zależy wynik całego działania. Z drugiej strony, jeśli już pierwszy jest fałszem, to wynik drugiego już się nie liczy, bo i tak całe działanie jest fałszem.

Logiczne OR

Tutaj sytuacja wygląda odwrotnie. Wystarczy, że co najmniej jeden z członów działania zwróci prawdę i już całe działanie jest prawdziwe. Innymi słowy, dostajemy fałsz tylko wtedy, gdy oba człony są fałszywe. Na potrzeby przykładu wyobraź sobie, że chcesz zaimplementować w swojej aplikacji tryb nocny, który będzie zmieniał kolorystykę, kiedy zrobi się ciemno. Dla ułatwienia ustalmy, że powinien się włączać w godzinach 0:00–5:59 i później 18:00–23:59.

function checkTime(currentTime) {
	return currentTime.getHours() < 6 || currentTime.getHours() > 18;
}

W takich sytuacjach JS też nie zwraca stricte wartości logicznej. Znowu dzieli sobie takie wyrażenie na dwa prostsze i analizuje je po kolei. Z tą różnicą, że teraz jeżeli pierwszy element zwróci true, to on zostaje zwrócony, w przeciwnym wypadku ten drugi. To przydawało się w momencie, kiedy przeglądarki nie obsługiwały domyślnych wartości dla parametrów. Wróćmy jeszcze na chwilę do ostatniej funkcji. Tutaj spodziewamy się parametru currentTime jako daty. Ale sam język nie zabrania nam wywołać tej funkcji bez żadnego argumentu. Możemy dodać wartość domyślną na dwa sposoby.

function checkTime(currentTime = new Date()) {
	return currentTime.getHours() < 6 || currentTime.getHours() > 18;
}
function checkTime(currentTime) {
	currentTime = currentTime || new Date();
	return currentTime.getHours() < 6 || currentTime.getHours() > 18;
}

Bardziej skomplikowane działania logiczne (prawa De Morgana)

Nie bój się tego tego podtytułu, bo za nim naprawdę nie kryją się żadne węże (ani nawet ogórki). Czasami potrzebujemy otrzymać wynik działania opierającego się o zaprzeczenia elementów składowych. Wiem dobrze, jak bardzo to potrafi być tricky. Wystarczy jednak, że zapamiętasz prostą zasadę:

!a && !b === !(a || b)
!a || !b === !(a && b)

Zasada w tych wzorach wygląda mniej więcej tak

Jeśli potrzebujesz użyć operatorów AND lub OR i oba elementy są poprzedzone zaprzeczeniem, to wystarczy ci jedno zaprzeczenie wyciągnięte przed nawias i zamieniony operator na ten drugi (zamiast && bierzesz || i odwrotnie).

Jak to możliwe, że taki trik w ogóle działa? Już tłumaczę na jednym przykładzie, drugi działa analogicznie, więc szkoda twojego czasu. Zaczniemy od ponownego przyjrzenia się przykładowi: !a && !b. Żeby to wyrażenie było prawdą, to zarówno !a, jak i !b muszą konwertować się do wartości logicznej true. Oznacza to, że zarówno a, jak i b muszą mieć wartość false (lub falsy). Gdy obie wartości są fałszem, to jest ten jedyny moment, kiedy działanie || jest zwraca wartość false. A, żeby z takiego pewnego fałszu zrobić prawdę, wystarczy mu zaprzeczyć.

Mam nadzieję, że twój mózg jeszcze się nie przegrzał z nadmiaru informacji. Ode mnie to tyle na dzisiaj, bo wiedzy i tak jest sporo. Mam nadzieję, że dowiedziałeś się czegoś nowego. Baw się dobrze i uważaj na siebie, bo łatwo o przeziębienia. Miau!