Operatory logiczne w JavaScript

Opublikowane przez lewy w dniu

W poprzednim wpisie – Rekrutacja frontend developer – dałem zajawkę co przeczytać będzie można w kolejnym wpisie, słowo się rzekło więc dziś o operatorach logicznych w JavaScript/TypeScript – && (koniunkcja) i || (alternatywa).

Niby temat banalny, bo co tu skomplikowanego w kodzie

const x = true;
const y = false;
if (x && y) {
    console.log('tego nie wyświetlimy');
}
if (x || y) {
    console.log('a to wyświetlimy na konsoli');
}

najbardziej intuicyjne ale czy najczęstsze zastosowanie operatorów logicznych?

Kod powyżej pokazuje wprost – zmienna x jest true, zmienna y false, więc pierwsze wyrażenie nie jest prawdziwe a drugie już tak, co skutkować będzie wyświetleniem tylko drugiego komunikatu na konsoli.

Cała zabawa zaczyna się w momencie gdy nie wiemy co będzie się kryło pod zmiennymi sprawdzanymi w wyrażeniach (dane przychodzą do nas np. z backendu).

Weźmy poniży przykład, nadal banalny i dość intuicyjny

const x = 1;
const y = 0;
if (x && y) {
    console.log('tego nie wyświetlimy');
}
if (x || y) {
    console.log('a to wyświetlimy na konsoli');
}

jak pewnie większość się domyśla pomimo zamiany true na 1 a false na 0, wyniki wyrażeń nie zmienią się i nadal na konsoli zobaczymy tylko drugi komunikat, ale co w takim przypadku

const x = 1;
const y = 0;
console.log(x && y); //output: 0
console.log(x || y); //output: 1

i zaczyna się zdziwienie, bo najczęściej udzielaną odpowiedzią (czyli spodziewanym rezultatem wyrażenia) jest false i true (zamiast 0 i 1)

I tu dochodzimy do meritum wpisu, wynikiem wyrażenia w których zastosujemy operatory logiczne nie jest true/false, a jedna z wartości sprawdzanych (występujących po obu stronach operatora).

Aby odpowiedzieć sobie na pytanie która, należy sobie uświadomić że w JavaScript (TypeScript) mamy tzw. wartości falsy i truthy („nieprawdziwawe” i „prawdziwawe” (?)). Silnik JS podczas przetwarzania kodu po napotkaniu operatora logiczne sprawdza najpierw jaka jest wartość zmiennej po lewej stronie operatora i na podstawie tego czy wartość ta jest falsy czy truthy to zwraca odpowiednią wartość.

A && B => A //A jest falsy
A && B => B //A jest truthy
A || B => A //A jest truthy
A || B => B //A jest falsy

Dla operatora && jeżeli wartość po jego lewej stronie jest falsy to wynikiem działania operatora jest ta wartość, jeżeli wartość po lewej stronie jest truthy to wynikiem działania jest wartość po jego prawej stronie.
Dla operatora || jeżeli wartość po jego lewej stronie jest truthy to wynikiem działania operatora jest ta wartość, jeżeli wartość po lewej stronie jest falsy to wynikiem działania jest wartość po jego prawej stronie.

Jeszcze należy sobie odpowiedzieć, które wartości to są truthy a które falsy i tu na szczęście wielkiego problemu nie ma, wartości falsy to

false
0
'' //pustry string
null
undefined

wszystkie inne to wartości truthy (m.in. pusty obiekt czy pusta tablica).

Kiedy już mamy taką wiedzą to jak możemy ją praktycznie wykorzystać i moje propozycje to

const req = getDataFromServer(); //pseudokod pobranie danych z serwera
const data = req || 'brak danych';

bardzo prosty przykład.

Pobieramy dane z backendu i oczekujemy, że dane te będą ciągiem znaków który chcemy zapisać do zmiennej aby coś z tym zrobić, ale jeżeli dane po stronie backendowej nie istnieją to chcemy zapisać komunikat „brak danych”. Zabezpieczamy się tym sposobem na zwrócenie przez serwer wartości pustego ciągu znaków czy np. nulla.

Praktycznym użyciem wykorzystania operatora && może być zabezpieczenie się przed najczęstszym błędem w JavaScript/TypeScript czyli
TypeError: Cannot read property ‚value’ of null

/*
getDataFromServer() zwraca json
{
  "site": {
    "url": "www.lewyino.pl"
  }
}
*/
const req = JSON.parse(getDataFromServer()); //pseudokod pobranie danych z serwera
const data = req && req.site && req.site.url;

w tym przypadku używając operatora && zapewniamy sobie, że dane które przyszły do nas są poprawne i na żadnym z poziomów zagnieżdżenia nie dostaliśmy null, bo jeżeli takiego nulla napotkaliśmy to wartość data będzie tym nullem, a nie otrzymamy wspomniany wcześniej błąd TypeError.

Operatory te oczywiście można dowolnie łączyć, należy tylko pamiętać, że jeżeli nie zastosujemy nawiasów do mocniejsze wiązanie ma && niż ||

przykłady z wpisu można sprawdzić tu https://jsbin.com/pecejinibe/edit?js,console

z ciekawostek, podobne zachowanie mamy w pythonie, tylko tam wartości falsy jest trochę więcej https://docs.python.org/3/library/stdtypes.html#truth-value-testing


0 Komentarzy

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *