NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 22 - Striktní operátory a přetypování v JavaScriptu

V minulé lekci, Dokončení editoru tabulek v JavaScriptu, jsme se do editoru tabulek naučili vkládat sloupce a řádky a mazat je.

V dnešním tutoriálu se budeme věnovat přetypování v JavaScriptu. Popíšeme si, jak se mění hodnoty proměnných při převodu z jednoho datového typu na jiný. To může totiž způsobit časté problémy zejména při porovnávání dvou hodnot v podmínkách. Přetypování nám však zároveň umožňuje zápis některých podmínek zkrátit, což si ukážeme na konkrétních příkladech.

Porovnávání a přetypování v JavaScriptu

Přetypování v JavaScriptu je proces, kdy se proměnná jednoho datového typu automaticky změní na jiný datový typ. Je dobré vědět, jak se při tomto procesu mění hodnoty těchto proměnných, abychom se vyhnuli nečekaným výstupům, zejména při jejich porovnání v podmínkách.

Přetypování je v JavaScriptu poměrně komplikované téma, proto mu věnujeme tuto samostatnou lekci. Nepokryjeme v ní všechny případy, které mohou nastat, ale získáme základní přehled o tom, jak přetypování v JavaScriptu funguje. Ukážeme si, jak se vyhnout možným problémům s přetypováním a kde nám přetypování naopak může pomoci psát přehlednější kód.

Striktní operátory

K porovnávání používáme relační operátory, které jsme si uvedli v lekci Podmínky v JavaScriptu. Víme, že mezi ně patří i striktní operátor === a jeho negace !==. Při porovnávání proměnných vrací první striktní operátor true pouze v případě, když jsou obě proměnné stejného datového typu a mají shodnou hodnotu. Operátor !== pak vrátí true, když porovnáváme rozdílné hodnoty nebo rozdílné datové typy.

Pro připomenutí si ukažme příklad, který demonstruje rozdíl mezi porovnáváním operátorem == a operátorem ===:

document.write('Rovnost hodnotou (1 == "1"): ' + (1 == '1') + '<br>');
document.write('Rovnost hodnotou a typem (1 === "1"): ' + (1 === '1') + '<br>');

Ukázka aplikace v prohlížeči:

== vs. ===
localhost

První podmínka se vyhodnotí jako pravdivá, protože se porovnávají jen hodnoty. Přesněji řečeno zde nejprve dojde k přetypování textu "1" (string) na číslo 1 (number) a následné porovnání se vyhodnotí jako true. U druhé podmínky kvůli striktnímu operátoru === k přetypování nedochází. Číslo se takto nemůže rovnat textu, proto se podmínka vyhodnotí jako false.

Ve většině případů je dobrým zvykem používat striktní operátory === a !== a nedovolit tak žádné přetypování při porovnávání.

Ukažme si ještě výstup podmínek s operátorem !==:

document.write((5 !== '5') + '<br>'); // true: Číslo 5 není rovno textu '5'.
document.write((10 !== 20) + '<br>'); // true: Hodnota dvou čísel je jiná.
document.write((5 !== 'five') + '<br>'); // true: Není rovna ani hodnota ani datový typ.
document.write(('five' !== 'five') + '<br>'); // false: Je rovna hodnota i datový typ.

V prohlížeči se nám vypíše:

!==
localhost

Vidíme, že tento operátor vrací ve většině případů true. Vrátí false pouze v případě, kdy porovnáváme dvě proměnné stejné hodnoty a stejného typu.

Zvláštnosti přetypování

Používání operátorů == a != při porovnávání různých datových typů může mít někdy nečekané výsledky, protože pravidla pro přetypování jsou mnohdy matoucí. Pro ukázku se nyní podívejme na pár typických výsledků přetypování, které bychom asi nečekali:

if ('' == '0') // false
if ('' == 0) // true
if (0 == '0') // true
if (false == 'false') // false
if (false == '0') // true
if (false == undefined) // false
if (false == null) // false
if (null == undefined) // true

Kdybychom v uvedené ukázce použili operátor ===, všechny podmínky by se vyhodnotily jako false. Ačkoli se může zdát, že nestriktní operátory (== a !=) jsou pohodlné díky automatickému přetypování porovnávaných hodnot, mohou být zdrojem neočekávaných chyb v kódu.

Kompletní výčet přetypování různých hodnot a datových typů při porovnávání operátorem == nalezneme v tabulce JavaScript Equality Table na GitHubu.

Zkrácení podmínek pomocí přetypování

Zatím jsme si ukázali jen problémy spojené s přetypováním a možnost, jak se jim vyhnout pomocí striktních operátorů. Pokud jsme si však jisti, že víme, co se během přetypování s danou proměnnou stane, je dobré jej při práci využít. Přetypování je nástroj, který nám může pomoci, ale zároveň způsobit problémy. Je tedy dobré se s ním naučit pracovat správně.

V této části se podíváme, jak využít automatické přetypování ve svůj prospěch, abychom dosáhli efektivnějšího a čistšího kódu.

Ověření neprázdného řetězce

Mějme příklad, kdy nám uživatel zadá své jméno a my chceme zkontrolovat, zda ho opravdu zadal. Budeme tedy kontrolovat, zda má zadané jméno délku větší než 0. Příklad by mohl vypadat následovně:

let jmeno = prompt('Vyplňte vaše jméno');
if (jmeno.length > 0)
    document.write('Jméno vyplněno.');
else
    document.write('Jméno nebylo vyplněno.');

Díky přetypování můžeme podmínku zkrátit pouze na:

let jmeno = prompt('Vyplňte vaše jméno');
if (jmeno.length)
    document.write('Jméno vyplněno.');
else
    document.write('Jméno nebylo vyplněno.');

Vlastnost length je typu number, který se při hodnotě 0 vyhodnotí jako false a při jakékoli jiné jako true.

Tu samou podmínku můžeme dokonce zapsat i jen takto:

let jmeno = prompt('Vyplňte vaše jméno');
if (jmeno)
    document.write('Jméno vyplněno.');
else
    document.write('Jméno nebylo vyplněno.');

Pokud by jméno nebylo vyplněno a místo něj byl uložený prázdný řetězec '', dojde k přetypování na false. V opačném případě na true.

Ověření neprázdného pole

Podobným postupem můžeme ověřit, zda máme prázdné pole nebo zda pole něco obsahuje:

let cisla = [1, 2, 3];
if (cisla.length)
    document.write('Pole čísel není prázdné.');
else
    document.write('Pole čísel je prázdné.');

Celý kód bude fungovat stejně, jako kdybychom v podmínce napsali (cisla.length > 0):

Kontrola pole
localhost

Zde však pozor! Jak jsme viděli, prázdný řetězec se vyhodnotí jako false. U pole je to rozdílné, prázdné pole se vyhodnotí jako true. Proto se u pole musíme ptát na jeho délku length.

V příkladu, kde je pole prázdné, se podmínka vyhodnotí jako nepravdivá:

let cisla = [];
if (cisla.length)
    document.write('Pole čísel není prázdné.');
else
    document.write('Pole čísel je prázdné.');

Výsledek:

Kontrola pole
localhost

Podmínky s null

Praktický příklad použití null v podmínce nám umožní metoda getElementById().

S metodou getElementById() jsme se seznámili v lekci Základy práce s DOM a události v JavaScriptu.

Tato metoda vrací v případě úspěchu první nalezený element, a to jako datový typ object. V případě neúspěchu vrací null, čímž poznáme, že se daný element na stránce nenachází.

Ukažme si příklad:

let htmlElement = document.getElementById('vysledek');
if (htmlElement !== null) {
    document.write('Element nalezen');
} else {
    document.write('Element nenalezen');
}

Jelikož se null přetypuje na false a object na true, můžeme podmínku zapsat i zkráceně:

let htmlElement = document.getElementById('vysledek');
if (htmlElement) {
    document.write('Element nalezen');
} else {
    document.write('Element nenalezen');
}

V případě, že se na naší stránce nalézá element se zadaným ID, například <span id="vysledek"></span>, podmínka se vyhodnotí jako pravdivá:

null
localhost

Zkrácený zápis podmínek je mezi mnoha vývojáři oblíbený zejména pro svou stručnost. Je tedy důležité mu porozumět i proto, abychom lépe chápali cizí kód. V situacích, kde lze jednoznačně rozlišit mezi pravdivou a nepravdivou hodnotou, je tento zápis efektivní a elegantní.

Podmínky s undefined

Jistě si pamatujeme, že datový typ undefined má proměnná, pokud ji deklarujeme a nepřiřadíme zatím žádnou hodnotu:

let vek;
document.write(typeof vek);

Výpis v prohlížeči:

undefined
localhost

Nastavení výchozí hodnoty parametru funkce pomocí undefined

Jako praktický příklad si ukážeme použití hodnoty undefined, na které narazíme ve starších kódech při nastavování výchozí hodnoty parametru funkce. Dříve se tento problém řešil takto:

function pozdrav(jazyk) {
    if (jazyk === undefined)
        jazyk = 'en'; // výchozí hodnota

    if (jazyk === 'en')
        document.write('Hello World!');
    else if (jazyk === 'cz')
        document.write('Ahoj světe!');

    document.write('<br>');
}

pozdrav();
pozdrav('cz');

Výsledek:

undefined
localhost

Funkce si nejprve otestuje, zda je parametr jazyk zadaný. Pokud není, přiřadí mu výchozí hodnotu 'en'.

Protože se undefined přetypuje na false, tak by nás možná napadlo ve funkci napsat podmínku ve tvaru:

if (!jazyk)
    jazyk = 'en';

To by v našem případě fungovalo, ale není to dobrý nápad. Zde je třeba mít na paměti, že pokud předáváme textový řetězec, prázdný string se opět vyhodnotí jako false. Podobně, pokud bychom předali číslo a nastavili hodnotu 0, i ta by byla vyhodnocena jako false. Zatímco prázdný řetězec nemusí v kontextu parametru pro jazykové nastavení dávat příliš smysl, prázdný oddělovač hodnot ('', bez mezery) nebo číslo 0 již mohou být v jiných situacích zadány úmyslně.

Nový zápis výchozí hodnoty parametru funkce

Díky standardu ES6 (ECMAScript 6) z roku 2015 lze výchozí hodnotu parametru funkce zapsat lépe. Výchozí hodnotu můžeme jednoduše přiřadit přímo k parametru při deklaraci funkce. Nemusíme tak poté kontrolovat, zda byl parametr zadán:

function pozdrav(jazyk = 'en') {
    if (jazyk === 'en')
        document.write('Hello World!');
    else if (jazyk === 'cz')
        document.write('Ahoj světe!');

    document.write('<br>');
}

pozdrav();
pozdrav('cz');

Výsledek bude stejný:

Výchozí hodnota parametru funkce
localhost

Shrnutí

V JavaScriptu existuje několik hodnot, které se při přetypování vyhodnotí jako false. Vzhledem k tomu, že mohou mít v kódu různé významy a použití, rozdělíme je do dvou skupin:

  • false, null a undefined – tyto hodnoty je vhodné porovnávat pomocí přetypování.
  • "" nebo '' (prázdný řetězec), číslo 0 a NaN – tyto hodnoty mohou mít vlastní význam v kódu, jak jsme zmínili výše. Někdy má smysl nastavit proměnné hodnotu 0, zadat jako parametr prázdný řetězec nebo uložit informaci o tom, že jsme získali nečíselný výsledek. Ale pozor, v podmínce se tyto tři hodnoty zpracují jako false, proto je ve většině případů lepší porovnávat je pomocí striktních operátorů.

Ukažme si přehled nejčastěji používaných hodnot a jejich vyhodnocení při přetypování v tabulce:

Zadaná hodnota v podmínce Výsledná hodnota
Infinity true
1 true
0 false
-1 true
-Infinity true
'1' true
'0' true
'-1' true
'true' true
'false' true
'' false
null false
undefined false
NaN false
[] true
{} (objekt) true
[[]] true
[0] true
[1] true

Vidíme zde i příklady, které jsme si již vyzkoušeli. Například prázdné pole [], které je v podmínce vyhodnoceno jako true. Tímto téma přetypování již kompletně opustíme.

V další lekci, Podmínky v JavaScriptu potřetí, se vrátíme k podmínkám a ukážeme si další konstrukce pro tvorbu podmínek.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 176x (1.32 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Jak se ti líbí článek?
Před uložením hodnocení, popiš prosím autorovi, co je špatněZnaků 0 z 50-500
Předchozí článek
Dokončení editoru tabulek v JavaScriptu
Všechny články v sekci
Základní konstrukce jazyka JavaScript
Přeskočit článek
(nedoporučujeme)
Podmínky v JavaScriptu potřetí
Článek pro vás napsal Roman
Avatar
Uživatelské hodnocení:
1129 hlasů
Roman
Aktivity