23. srpna 2022

Logické operátory

V JavaScriptu jsou čtyři logické operátory: || (OR – nebo), && (AND – a), ! (NOT – ne), ?? (koalescence). V tomto článku vysvětlíme první tři, operátor ?? bude vysvětlen v dalším článku.

Ačkoli se nazývají „logické“, mohou být použity na hodnoty libovolného typu, nejenom boolean. Také jejich výsledek může být jakéhokoli typu.

Podívejme se na podrobnosti.

|| (OR)

Operátor „OR“ („nebo“) je reprezentován dvěma svislými čarami za sebou:

výsledek = a || b;

V klasickém programování je logické OR určeno pouze k manipulaci s booleovskými hodnotami. Je-li některý z jeho argumentů true, vrátí true, jinak vrátí false.

V JavaScriptu je tento operátor trochu rafinovanější a silnější. Nejprve se však podívejme, co se stane s hodnotami typu boolean.

Existují čtyři možné logické kombinace:

alert( true || true );   // true
alert( false || true );  // true
alert( true || false );  // true
alert( false || false ); // false

Jak vidíme, výsledek je vždy true kromě případu, kdy jsou oba operandy false.

Není-li operand typu boolean, je pro účel vyhodnocení převeden na boolean.

Například číslo 1 se převede na true, číslo 0 na false:

if (1 || 0) { // funguje stejně jako if ( true || false )
  alert( 'pravda!' );
}

Většinou se OR || používá v příkazu if k otestování, zda některá ze zadaných podmínek je true.

Příklad:

let hodina = 9;

if (hodina < 10 || hodina > 18) {
  alert( 'Úřad má zavřeno.' );
}

Můžeme předat další podmínky:

let hodina = 12;
let jeVíkend = true;

if (hodina < 10 || hodina > 18 || jeVíkend) {
  alert( 'Úřad má zavřeno.' ); // je víkend
}

OR „||“ najde první pravdivou hodnotu

Výše uvedená logika je vcelku klasická. Nyní se podívejme na „extra“ vlastnosti JavaScriptu.

Rozšířený algoritmus funguje následovně.

Zadáme více hodnot, spojených ORem:

výsledek = hodnota1 || hodnota2 || hodnota3;

Operátor OR || provádí následující:

  • Vyhodnocuje operandy zleva doprava.
  • Každý operand převede na typ boolean. Je-li výsledek true, zastaví se a vrátí původní hodnotu tohoto operandu.
  • Pokud byly vyhodnoceny všechny operandy (tj. všechny byly false), vrátí poslední operand.

Hodnota se vrátí ve své původní podobě bez konverze.

Jinými slovy, řetězec ORů "||" vrátí první pravdivou hodnotu, a pokud není žádná pravdivá hodnota nalezena, vrátí poslední hodnotu.

Příklad:

alert( 1 || 0 ); // 1 (1 je pravdivá)

alert( null || 1 ); // 1 (1 je první pravdivá hodnota)
alert( null || 0 || 1 ); // 1 (první pravdivá hodnota)

alert( undefined || null || 0 ); // 0 (všechny jsou nepravdivé, vrátí poslední hodnotu)

To umožňuje některé zajímavé způsoby použití ve srovnání s „čistým, klasickým, pouze booleovským ORem“.

  1. Získání první pravdivé hodnoty ze seznamu proměnných nebo výrazů.

    Například máme proměnné jméno, příjmení a přezdívka, všechny jsou nepovinné (tj. mohou být undefined nebo obsahovat hodnoty nepravda).

    Vybereme pomocí OR || tu, která obsahuje data, a zobrazíme je (není-li nastaveno nic, zobrazíme anonym):

    let jméno = "";
    let příjmení = "";
    let přezdívka = "SuperCoder";
    
    alert( jméno || příjmení || přezdívka || "anonym"); // SuperCoder

    Kdyby všechny proměnné obsahovaly hodnotu nepravda, zobrazil by se anonym.

  2. Zkrácené vyhodnocení.

    Další vlastností operátoru OR || je tzv. „zkrácené“ vyhodnocení.

    Znamená to, že || zpracovává své argumenty, dokud nenarazí na první pravdivou hodnotu, a pak tuto hodnotu okamžitě vrátí, aniž by se byť jen dotkl dalších argumentů.

    Důležitost této vlastnosti se projeví, jestliže operandem nebude pouhá hodnota, ale výraz s vedlejším efektem, například přiřazení proměnné nebo volání funkce.

    V níže uvedeném příkladu se zobrazí jen druhá zpráva:

    true || alert("nezobrazí se");
    false || alert("zobrazí se");

    Operátor OR || na prvním řádku se přestane vyhodnocovat ihned poté, co narazí na true, takže alert se nevykoná.

    Někdy lidé využívají tuto vlastnost k tomu, aby vykonali příkaz jen tehdy, není-li splněna podmínka na levé straně.

&& (AND)

Operátor „AND“ („a“) je reprezentován dvěma znaky „ampersand“ &&:

výsledek = a && b;

V klasickém programování AND vrací true, jsou-li oba operandy pravdivé, a false jinak:

alert( true && true );   // true
alert( false && true );  // false
alert( true && false );  // false
alert( false && false ); // false

Příklad s if:

let hodina = 12;
let minuta = 30;

if (hodina == 12 && minuta == 30) {
  alert( 'Je právě 12:30' );
}

Stejně jako u OR může být operandem AND jakákoli hodnota:

if (1 && 0) { // vyhodnotí se jako true && false
  alert( "nevykoná se, protože výsledkem je nepravda" );
}

AND „&&“ najde první nepravdivou hodnotu

Mějme několik hodnot spojených ANDem:

výsledek = hodnota1 && hodnota2 && hodnota3;

Operátor AND && provádí následující:

  • Vyhodnocuje operandy zleva doprava.
  • Každý operand převede na typ boolean. Je-li výsledek false, zastaví se a vrátí původní hodnotu tohoto operandu.
  • Pokud byly vyhodnoceny všechny operandy (tj. všechny byly pravdivé), vrátí poslední operand.

Jinými slovy, řetězec ANDů "&&" vrátí první nepravdivou hodnotu, a pokud není žádná nepravdivá hodnota nalezena, vrátí poslední hodnotu.

Výše uvedená pravidla se podobají operátoru OR. Rozdíl spočívá v tom, že AND najde první nepravdivou hodnotu, zatímco OR najde první pravdivou.

Příklady:

// je-li první operand pravdivý,
// AND vrátí druhý operand:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// je-li první operand nepravdivý,
// AND ho vrátí. Druhý operand se pak ignoruje.
alert( null && 5 ); // null
alert( 0 && "je jedno co" ); // 0

Můžeme předat i více hodnot za sebou. Podívejme se, jak se vrátí první nepravdivá:

alert( 1 && 2 && null && 3 ); // null

Když jsou všechny hodnoty pravdivé, vrátí se poslední z nich:

alert( 1 && 2 && 3 ); // 3, poslední hodnota
Priorita AND && je vyšší než priorita OR ||

Priorita operátoru AND && je vyšší než priorita operátoru OR ||.

Kód a && b || c && d je tedy v zásadě stejný, jako kdyby výrazy s && byly uzavřeny do závorek: (a && b) || (c && d).

Nenahrazujte příkaz if operátorem || nebo &&

Někdy lidé používají operátor AND && jako „kratší variantu if“.

Příklad:

let x = 1;

(x > 0) && alert( 'Větší než nula!' );

Akce napravo od && se vykoná jen tehdy, když k ní dospěje vyhodnocování, tedy jen když (x > 0) platí.

Máme tedy v zásadě analogii k:

let x = 1;

if (x > 0) alert( 'Větší než nula!' );

Ačkoli varianta s && se zdá být kratší, if je zřejmější a obvykle bývá trochu čitelnější. Doporučujeme tedy používat každou konstrukci k tomu, k čemu byla stvořena: používejte if, chcete-li „pokud“, a používejte &&, chcete-li AND.

! (NOT)

Booleovský operátor „NOT“ („ne“) je reprezentován vykřičníkem !.

Jeho syntaxe je velice jednoduchá:

výsledek = !hodnota;

Tento operátor přijímá jediný argument a provádí následující:

  1. Převede operand na typ boolean: true/false.
  2. Vrátí opačnou hodnotu.

Příklad:

alert( !true ); // false
alert( !0 ); // true

Někdy se používá dvojité NOT !! ke konverzi hodnoty na typ boolean:

alert( !!"neprázdný řetězec" ); // true
alert( !!null ); // false

Znamená to, že první NOT převede hodnotu na boolean a vrátí opak, druhý NOT jej znovu převrátí. Na konci tedy máme planou konverzi na boolean.

Existuje trochu výmluvnější způsob, jak udělat totéž – vestavěná funkce Boolean:

alert( Boolean("neprázdný řetězec") ); // true
alert( Boolean(null) ); // false

Operátor NOT ! má nejvyšší prioritu ze všech logických operátorů, takže se vždy vykoná jako první, dříve než && nebo ||.

Úlohy

důležitost: 5

Co vypíše níže uvedený kód?

alert( null || 2 || undefined );

Odpověď zní 2, což je první pravdivá hodnota.

alert( null || 2 || undefined );
důležitost: 3

Co vypíše níže uvedený kód?

alert( alert(1) || 2 || alert(3) );

Odpověď zní: nejprve 1, pak 2.

alert( alert(1) || 2 || alert(3) );

Volání alert nevrátí žádnou hodnotu, jinými slovy vrátí undefined.

  1. První OR || vyhodnotí svůj levý operand alert(1). Ten zobrazí první zprávu obsahující 1.
  2. Tento alert vrátí undefined, takže OR ve svém hledání pravdivé hodnoty přejde ke druhému operandu.
  3. Druhý operand 2 je pravdivý, takže vyhodnocení operátoru se zastaví, vrátí 2 a to je pak zobrazeno vnějším alertem.

Nezobrazí se 3, protože vyhodnocení se k alert(3) nedostane.

důležitost: 5

Co vypíše níže uvedený kód?

alert( 1 && null && 2 );

Odpověď zní null, protože je to první nepravdivá hodnota v seznamu.

alert(1 && null && 2);
důležitost: 3

Co vypíše níže uvedený kód?

alert( alert(1) && alert(2) );

Odpověď zní: nejprve 1, pak undefined.

alert( alert(1) && alert(2) );

Volání alert vrátí undefined (funkce jen zobrazí zprávu, takže její návratová hodnota nemá žádný význam).

Proto && vyhodnotí první operand (vypíše 1) a okamžitě se zastaví, protože undefined je nepravdivá hodnota. Operátor && hledá první nepravdivou hodnotu a vrátí ji, takže je hotov.

důležitost: 5

Jaký bude výsledek?

alert( null || 2 && 3 || 4 );

Odpověď zní: 3.

alert( null || 2 && 3 || 4 );

Operátor AND && má vyšší prioritu než ||, proto se vykoná jako první.

Výsledek 2 && 3 = 3, takže z výrazu se stane:

null || 3 || 4

Nyní bude výsledkem první pravdivá hodnota: 3.

důležitost: 3

Napište podmínku „if“, která ověří, že proměnná věk má hodnotu mezi 14 a 90 včetně.

„Včetně“ znamená, že podmínka je splněna i tehdy, je-li věk 14 nebo 90.

if (věk >= 14 && věk <= 90)
důležitost: 3

Napište podmínku „if“, která ověří, zda proměnná věk NENÍ mezi 14 a 90 včetně.

Vytvořte dvě varianty: první bude používat NOT !, druhá se obejde bez něj.

První varianta:

if (!(věk >= 14 && věk <= 90))

Druhá varianta:

if (věk < 14 || věk > 90)
důležitost: 5

Který z těchto alertů se vykoná?

Jaké budou výsledky výrazů uvnitř if(...)?

if (-1 || 0) alert( 'první' );
if (-1 && 0) alert( 'druhý' );
if (null || -1 && 1) alert( 'třetí' );

Odpověď zní: vykoná se první a třetí alert.

Podrobnosti:

// Vykoná se.
// Výsledek -1 || 0 = -1, tedy pravda.
if (-1 || 0) alert( 'první' );

// Nevykoná se.
// -1 && 0 = 0, nepravda.
if (-1 && 0) alert( 'druhý' );

// Vykoná se.
// Operátor && má vyšší prioritu než ||,
// takže -1 && 1 se vykoná jako první, což dává tento řetězec:
// null || -1 && 1  ->  null || 1  ->  1
if (null || -1 && 1) alert( 'třetí' );
důležitost: 3

Napište kód, který se pomocí prompt zeptá na přihlášení.

Jestliže návštěvník zadá "Správce", zeptejte se ho pomocí prompt na heslo. Bude-li vstupem prázdný řádek nebo uživatel stiskne Esc, zobrazte „Zrušeno“. Bude-li zadán jiný řetězec, zobrazte „Neznám vás“.

Heslo se ověří následovně:

  • Pokud se rovná „Vládce“, tak zobrazte „Vítáme vás!“.
  • Při jiném řetězci zobrazte „Špatné heslo“.
  • Bude-li zadán prázdný řetězec nebo bude vstup zrušen, zobrazte „Zrušeno“.

Schéma:

Použijte vnořené bloky if. Dbejte na celkovou čitelnost kódu.

Nápověda: po zadání prázdného vstupu prompt vrátí prázdný řetězec ''. Po stisknutí klávesy ESC vrátí null.

Spustit demo

let uživatelskéJméno = prompt("Kdo je tam?", '');

if (uživatelskéJméno === 'Správce') {

  let heslo = prompt('Heslo?', '');

  if (heslo === 'Vládce') {
    alert( 'Vítáme vás!' );
  } else if (heslo === '' || heslo === null) {
    alert( 'Zrušeno' );
  } else {
    alert( 'Špatné heslo' );
  }

} else if (uživatelskéJméno === '' || uživatelskéJméno === null) {
  alert( 'Zrušeno' );
} else {
  alert( "Neznám vás" );
}

Všimněte si svislého odsazení uvnitř bloků if. Není technicky vyžadováno, ale činí kód čitelnějším.

Mapa tutoriálu

Komentáře

přečtěte si před komentováním…
  • Máte-li návrhy na zlepšení, vytvořte prosím issue na GitHubu nebo pull request místo komentáře.
  • Pokud v článku něčemu nerozumíte, napište prosím, čemu přesně a na kterém místě.
  • Pro vložení několika slov kódu použijte značku <code>, pro několik řádků je obalte značkou <pre>, pro více než 10 řádků vložte odkaz na pískoviště (plnkr, jsbin, codepen…)