Praktický JavaScript (1.) - Truthy a Falsy vs. true a false

Publikoval Michal Kočí dňa 29.05.2016 o 13:00 v kategórii JavaScript

V JavaScripte máme boolean dátový týp, ktorý môže nadobúdať hodnoty true a false, to je veľmi podobné aj iným programovacím jazykom. Čo však máme navyše je Truthy a Falsy, čo sú síce podobné hodnoty, ale ich využitie je oveľa širšie. Poďme sa na ne pozrieť.

JavaScript má dátový typ Boolean...

...ale v JavaScripte má všetko okrem svojej vlastnej aj pravdivostnú hodnotu. Tieto hodnoty sa volajú Truthy a Falsy. A najlepšie na nich je, že ich vieme použiť všade tam, kde by ste mohli použiť Boolean. Pozrime sa najskôr ale na to, čo je Truthy a čo Falsy.

Falsy a Truthy

Hodnotu Falsy, teda akúsi obdobu hodnoty false, majú:

  • false
  • nula (0)
  • prázdny reťazec ('')
  • špeciálna číselná hodnota NaN (not a number)
  • null
  • undefined

Hodnotu Truthy (obdobu true) má všetko, čo nemá hodnotu Falsy. Teda napríklad:

  • true
  • akékoľvek číslo nerovné nule
  • akýkoľvek neprázdny reťazec
  • ľubovoľný objekt
  • ľubovoľné, aj prázdne, pole
  • ktorákoľvek funkcia (samotná funkcia, nie jej hodnota)

Najčastejšie použitie: if a while

Určite viete, že if či while potrebujú k svojmu fungovaniu výraz vracajúci Boolean a na základe jeho hodnoty sa patričný blok vykoná alebo nevykoná. Tak to funguje zrejme v každom programovacom jazyku.

V JavaScripte je to trochu inak. if či while neočakávajú Boolean ale pravdivostnú hodnotu. A čo má v JavaScripte pravdivostnú hodnotu? Presne tak, všetko.

Poďme na príklad. Potrebujete spustiť kód iba ak má pole arr aspoň jeden prvok. Jednoduché:

if(arr.length > 0) {
  console.log('Neprazdne pole');
}

Uvedený kód sa dá však zapísať kratšie ovšem s úplne rovnakou funkcionalitou. Využijeme vedomosť, že nula je Falsy. Preto môžeme kód prepísať nasledovne.

if(arr.length)
{
  console.log('Neprazdne pole');
}

Pokiaľ je veľkosť pola (arr.length) nula, t.j. pole neobsahuje žiaden prvok, hodnota vráti Falsy. if blok sa teda nevykoná, lebo if očakáva Truthy/Falsy hodnotu (a nie true/false). Ak pole obsahuje aspoň jeden prvok, hodnota arr.length bude nenulová, t.j. Truthy a teda blok sa vykoná.

Prehľadný kód

Možno si vravíte, že prvý zápis je opisnejší, jasnejší či zrozumiteľnejší. Že viete presne čo sa deje. Kdežto druhý je mierne komplikovanejší na porozumenie. Možno. A možno nie. Záleží na tom, ako JavaScript poznáte. Na druhom zápise nie je nič zlé ani nemorálne.

Môj názor na vec je nasledovný:

  • Znalosť Truthy/Falsy by mala patriť k znalostiam každého JavaScript programátora. Preto by som sa nebál ju používať, ale...
  • ... vždy uprednostnite konvencie tímu prípadne čitateľnosť. Takže ak vám či vášmu tímu vyhovuje skôr prvý príklad, kľudne ho naďalej používajte.

Čo je v skutočnosti dôležité? Aby ste zápisu, t.j. Truthy a Falsy hodnotám rozumeli. Ak ich aj nebudete sami používať, verte, že niekto iný bude. A v programovaní často musíte/chcete čítať kód niekoho iného. Takže odteraz vás druhý zápis nemôže prekvapiť.

Chcete sa poriadne naučiť JavaScript a ešte sa pritom naučiť nejaký framework či knižnicu (napríklad Angular či React)? Prídite na niektoré z mojich JavaScriptových školení a naučte sa to rýchlo a jednoducho.

Logické operátory || (OR) a && (AND)

Logické operátory OR a AND tiež v JavaScripte fungujú s Truthy/Falsy hodnotami.

Definovať ich môžeme nasledovne:

  • Operátor OR (||) vráti hodnotu, ak aspoň jeden výraz je Truthy
  • Operátor AND (&&) vráti hodnotu, ak všetky hodnoty sú Truthy

Oba operátory navyše skracujú vyhodnocovanie, čo tiež isto poznáte z iných jazykov. Kontrola výrazov končí v momente, kedy je jasný výsledok celého výrazu (vyhodnocuje sa postupne zľava):

  • Pri OR hneď, keď niektorý výraz vráti Truthy
  • Pri AND hneď, keď niektorý výraz vráti Falsy

Výsledkom výrazu je hodnota

Fajn, toto asi nebolo moc prekvapivé, však? Ale všimli ste si, že som slovo hodnotu dal tučným? Náhoda? Omyl? Ani jedno...

V programovacích jazykoch, v ktorých s operátormi OR a AND môžete použiť iba Boolean hodnoty je výsledkom neprekvapivo Boolean hodnota.

V JavaScripte však s OR a AND môžete použiť čokoľvek, očakávajú totiž Truthy/Falsy, čiže čokoľvek. Čo je teda výsledkom celého výrazu?

  • Pri OR je výsledkom prvá Truthy hodnota. Ak výraz neobsahuje Truthy hodnotu, výsledkom je posledná hodnota výrazu.
  • Pri AND je výsledkom prvá Falsy hodnota. Ak výraz neobsahuje Falsy hodnotu, výsledkom je posledná hodnota výrazu.

Zdá sa vám znalosť tejto funkcionality zbytočná? Verte, nie je. Má veľmi praktické využitie, na ktoré sa teraz pozrieme.

Praktické využitie operátora OR

Kde sa nám teda tá mierne nudná teória hodí? S operátorom OR sa nám hodí, pokiaľ chceme používať defaultné hodnoty.

JavaScript do verzie ES5 nepodporuje pre parametre funkcií defaultné hodnoty. Ak sme chceli niečo ako defaultné hodnoty používať, museli sme si to zabezpečiť sami.

Predstavte si síce neužitočnú funkciu, pre náš príklad však vhodnú, ktorá vám do konzoly dokáže vypísať jeden a ten istý reťazec požadovane-krát. No a ak volajúci nešpecifikuje koľko krát (alebo povie nula-krát), tak chete reťazec vypísať presne raz. A ak nešpecifikuje reťazec, chcete vypísať Hello World.

function printXTimes(str, times) {
  var i;
  if(!str) {
    str = 'Hello World';
  }
  if(!times) {
    times = 1;
  }
  for(i=0; i<times; i++) {
    console.log(str);
  }  
}

Docela ukecané, však? A to už Truthy/Falsy používame v if podmienkach. Takto by však mohla vyzerať skrátená verzia, ak použijeme OR operátor:

function printXTimes(str, times) {
  var i;
  str = str || 'Hello World';
  times = times || 1;
  for(i=0; i<times; i++) {
    console.log(str);
  }  
}

Kratšie a pravdepodobne aj prehľadnejšie, však? Tak si len v skratke zopakujme, ako to funguje.

Ak voľajúci ako hodnotu parametra str pošle Falsy hodnotu (null, undefined, prázdny reťazec, ...) tak JavaScriptový engine uvidí, že prvá časť výrazu je Falsy a ide vyhodnotiť druhú časť (náš reťazec). A vráti práve túto hodnotu. Jednak preto, lebo táto je Truthy, ale aj keby nebola, tak je to posledná podmienka, takže sa vráti jej hodnota tak či tak.

No a takto jednoducho sme zabezpečili defaultné hodnoty pre naše parametre. Zase platí, pokiaľ s tým nie ste mentálne kompatibilný, kľudne použite ukecanejší spôsob. Ale pamätajte si, ako OR funguje, aby vás neprekvapil nejaký existujúci kód.

Praktické využitie AND operátora

Aké je praktické využitie operátora AND? Bez väčšieho napínania vám to prezradím. Je ním volanie callbackov, t.j. volanie funkcií predaných do funkcie.

V JavaScripte často prijímajú funkcie iné funkcie, ktoré majú v istý moment zavolať. Ľudovo sa volajú callbacky. Lenže, nie vždy sú to povinné parametre a vy takúto funkciu chcete zavolať len keď vám bola predaná.

Toto je potom príklad, kde máte funkciu, ktorá vie niečo urobiť a keď je hotová, zavolá callback. Najčastejšie je asi použitie pri asynchronných operáciách (napríklad načítanie dát cez HTTP):

function loadDocument(url, callback) {
    var r = new XMLHttpRequest();
    r.onreadystatechange = function() {
      if(r.readyState===4 && r.status===200) {
        var data = JSON.parse(r.responseText);
        if(callback) {
          callback(data)
        }
      }
    }
    r.open('GET', url, true);
    r.send();
}

Kde v príklade vieme použiť operátor AND? V kontrole, či nám dorazil parameter callback:

function loadDocument(url, callback) {
    var r = new XMLHttpRequest();
    r.onreadystatechange = function() {
      if(r.readyState===4 && r.status===200) {
        var data = JSON.parse(r.responseText);
        callback && callback(data);
      }
    }
    r.open('GET', url, true);
    r.send();
}

Ako to funguje? JavaScriptový engine sa pozrie na prvú hodnotu. Ak je táto Falsy, skráti vyhodnocovanie, vráti jeho hodnotu a druhý výraz už vyhodnocovať nebude (t.j. nebude sa snažiť spustiť funkciu).

Uznávam, nejedná sa o žiadnu extra veľkú úsporu. Navyše, toto je jedno zo skrátení, ktoré osobne nepoužívam, nepríde mi prehľadné. Ale zase, je dobré o ňom vedieť. A mimochodom, často ho používajú práve minifikátory.

Operátor negácie (!) a pretypovanie

Niekedy sa hodí z pravdivostnej hodnoty (Truthy/Falsy) spraviť pravý Boolean (true/false). Napríklad keď výsledok bude ukladať ako JSON. Ako na to?

Operátor logický NOT (!) slúži na negáciu výrazu. Opäť, pri tradičných jazykoch spraví z true false a z false true. Lenže v JavaScripte sa dá použiť na ľubovoľný výraz (Truthy/Falsy).

Pokiaľ je výraz Truthy, výsledok aplikovania tohto operátora bude false. A pokiaľ je Falsy, výsledkom bude true.

var obj = null; // obj je Falsy
var b = !obj; // b bude true

Toto už skoro robí to, čo by sme chceli, teda mení čokoľvek na Boolean, žiaľ na presne opačnú hodnotu, ako by sme chceli. Ako znegovať výslednú hodnotu? Predsa tým istým operátorom:

var obj = null; // obj je Falsy
var b = !!obj; // b bude false

Takže keď budete z Truthy/Falsy hodnoty chcieť získať pravý Boolean, stačia vám k tomu dva výkričníky.

Len pre zaujímavosť, toto fungovanie tiež často používajú minifikátory a v minifikovanom kóde namiesto true nájdete hodnotu !0 a namiesto false hodnotu !1.

Záverom

Tak ako, dočítali ste až sem? Poznali ste Truthy a Falsy a ich využitie? Podeľte sa v komentároch, ktoré sa vám zdá vhodné a ktoré už až moc nečitateľné...

Mohlo by ťa tiež zaujímať

Páčil sa ti príspevok?

Zdieľaj príspevok alebo si ho odlož na neskôr

Sleduj ma

Ak nechceš premeškať príspevky ako je tento, sleduj ma na Twitteri, alebo ak máš RSS čítačku, môžeš sledovať môj RSS kanál.

Komentáre

K tomuto článku nie su pridané žiadne komentáre.

Pridať komentár

Máš niečo zaujímavé povedať k článku? Pridaj to k článku ako komentár. Spam, reklamu alebo inak nerelevantné komentáre okamžite mažem.

Pridanie komentára sa nepodarilo. Oprav si prosím chyby.