(13): ECMAScript 5 – Boolean

Komentáře: 2

23.7.2010 00:11 — Bronislav Klučka — ECMAScript 5

Na řadě je typ Boolean. Dnešní článek se bude věnovat hodnotám s primitivním typem Boolean i objektům s konstruktorem Boolean, jak jsou definovány v ECMAScriptu 5.

Specifikace ECMAScript 5 nepřináší pro typ Boolean nic nového, ale nebude vadit, když si představíme i tento typ.

Podíváme se i na konverze na tento typ, operátory a použití && a || jako guard a default.

Literály Boolean hodnot

Proměnné typu Boolean (ať už primitivní, nebo hodnoty objektů s tímto konstruktorem) mohou nabývat 2 hodnot. Tyto hodnoty sami o sobě představují typ Boolean. Jedná se o literály true a false.

kód 1: použití literálů
// definice 2 proměnných typu Boolean,
// použitím literálů je tento typ definován
// proměnné
var a = true,
    b = false;
      

Primitivní typ Boolean

Primitivní typ Boolean je typem reprezentujícím logické entity, který má 2 hodnoty true a false. Vytvoření proměnné tohoto typů je shodné s použitím literálu (vizte kód 1).

Konstruktor Boolean

Tento typ má i svou objektovou podobu a tou jsou objekty s konstruktorem Boolean. Je nutné si uvědomit, že se skutečně jedná o objekty.

Konstruktor volaný funkcí

Volání konstuktoru Boolean jako funkce neprovádí vytvoření nového objektu, ale typovou konverzi. Návratová hodnota je tedy promitivního typu Boolean, nikoliv objektem s konstruktorem Boolean.

Standardní volání konstruktoru

Je-li Boolean voláno jako část new výrazu, jedná se o konstruktor, který vrací nový objekt. Tento objekt má interní vlastnost, která drží primitivní hodnotu, která byla předána konstruktoru, tato hodnota je potom logickou hodnotou daného objektu. Přesněji řečeno, je-li potřeba převést objekt tohoto typu na primitivní hodnotu, je volána funkce Boolean.prototype.valueOf(), terá vrací tuto interní hodnotu.

Nasledující ukázka demonstruje použití různých konstrukcí pro vytvoření proměnné typu Boolean a vlastnosti primitivního typu a objektu.

kód 2: Vlastnosti typu Boolean v závislosti na konstruktoru
var a = true,                // a = true,  typeof a = boolean,
    b = new Boolean(false),  // b = false, typeof b = object,
    c = Boolean(false),      // c = false, typeof c = boolean,
    d = b,                   // d = false, typeof d = object,
    e = Boolean(5),          // e = true, typeof e = boolean,


b.name = 'brona';   // b.name = 'brona', d.name = 'brona'
                    // zde je nutné si uvědomit, že pracujeme s
                    // objekty: je možné je rozšiřovat (přidávat
                    // nové vlastnosti) a při přiřazováni pracujeme
                    // s daným objektem, nikoliv s kopií, proto
                    // i objekt "d" bude mít novou vlastnost

c.name = 'brona';   // c.name = undefined
                    // interpret povolí syntaxi rozšíření, ale
                    // nad primitivní hodnotou jej neprovede

if (a)...           // toto projde
if (c)...           // toto neprojde
if (b)...           // toto projde, b je objekt
if (b.valueOf())... // toto neprojde


      

Vlastnosti a metody konstruktoru Boolean

Jedná se o vlastnosti a metody, které se volají přímo konstruktoru Boolean.

Boolean.prototype

Prototypový objekt typu Boolean.

Vlastnosti a metody prototypu objektu Boolean

Jedná se o vlastnosti a metody, které se volají proměnné vytvořené pomocí konstruktoru Boolean.

Boolean.prototype.constructor

Konstruktor proměnné typu Boolean.

kód 3: Boolean.prototype.constructor
var x = new Boolean(true);
var y = x.constructor(false); // nový objekt s hodnotou false
alert(y);                     // false
      
Boolean.prototype.toString()

Funkce vrací řetězcovou podobu primitivní hodnoty daného objektu.

kód 4: Boolean.prototype.toString()
var x = new Boolean(true);
alert(x.toString());      // "true"
      
Boolean.prototype.valueOf()

Funkce vrací primitivní hodnotu daného objektu.

kód 5: Boolean.prototype.valueOf()
var x = new Boolean(true);
alert(x.valueOf());      // true
      

Převod na hodnotu typu Boolean

Převod na hodnotu typu Boolean se provádí, pokud je ve výrazu očekávána logická hodnota, nebo má být logická hodnota výsledkem daného výrazu.

Převod se provádí pomocí interní funkce ToBoolean(value) na základě následující tabulky.

Převod na hodnotu typu Boolean
TypVýsledek
Undefinedfalse
Nullfalse
BooleanPodle vlastní hodnoty proměnné
NumberJe-li hodnota +0, -0, NaN, potom je převedena na false, jinak na true
StringJe-li hodnota prázdným řetězcem (délka 0), potom je převedena na false, jinak na true
Objecttrue

Operátory

ECMAScript je sice typový jazyk, ale operátory jsou definované jako netypové, nejsou žádné typy očekávány. Interpret/compiler musí provádět operace nad všemi typy.

Operátory s logickým výstupem

Podívejme se na operátory, jejichž výstupem (výsledkem dané operace) je logická hodnota.

delete
Unární operátor, výsledkem je logická hodnota říkající, zda se vazbu (binding či reference) podařilo odstranit.
!
Unární operátor, který vrací false, pokud operand je truthy, jinak vrací true (vizte tabulku převodů).
<, <=, >, >=
Binární relační operátory.
A instanceof B
Binární operátor, výsledkem je true, pokud objekt A byl vytvořen konstruktorem B, nebo je B libovolným předkem v prototypovém řetězci.
A in B
Binární operátor, výsledkem je true, pokud objekt B má vlastnost s názvem A.
== != === !==
Binární operátory rovnosti.
Vynucení logické hodnoty

Pokud potřebujete proměnnou převést na typ Boolean, máte i jinou možnost, než použít funkci Boolean. Použití dvojté negace toto učiní také. První si vynutí převedení na typ Boolean a obrátí hodnotu, druhá negace hodnotu vrátí na odpovídající.

kód 6: Dvojitá negace
var x = 5;
alert(!!x);   // true
      
Operátory && a ||

Pokud jste v předchozím seznamu nenašli binární operátory && a ||, nedivte se, není to chyba. ECMAScript totiž definuje jejich chování takto:

A && B
Je-li A falsy, vrať A, jinak vrať B.
A || B
Je-li A truthy, vrať A, jinak vrať B.
kód 7: Operátory && a ||
alert("" && 1);         // "" (falsy)
alert("brona" && 0);    // 0 (falsy)
alert("" || "brona");   // "brona" (truthy)
alert(4 || 0);          // 4 (truthy)
      

Výše zmíněný postup vlastně funguje, jako by pracoval s logickými hodnotami bez ohledu na typ operandů. Vlastně jsme na něj zvyklí. Ale nabízí více, něž jen prosté vyhodnocování.

Default

Operátoru || se také říká default, protože často slouží k nastavení výchozí hodnoty.

Měli byste vědět, že pokud není zadána proměnná do funkce, ECMAScript ji naplní hodnotou undefined. Řekněme, že máme funkci A(b) a chceme, aby pokud nebude zadán parametr b, byla použita hodnota 1

kód 8: Default
// můžeme použít podmínku
function A(b)
{
  if (undefined === b)
    b = 1;
  // další kód
}

// můžeme použít podmiňovací operátor
function A(b)
{
  b = (undefined === b) ? 1 : b;
  // další kód
}

// můžeme použít default
function A(b)
{
  b = b || 1; // nebude-li definováno b, nastaví se 1
  // další kód
}
      

Nemusíme se omezovat pouze na proměnné, vyhodnocován je celý výraz:

kód 9: Default
/*
Následující ukázka převede objekt na řetězec
pomocí funkcí processDate, processArray,
nebo processRegExp
na základě toho, zda se jedná o Date,
Array, anebo RegExp
*/
var s = '';
function processDate(obj)
{
  if (obj instanceof Date)
  {
    s += obj.toLocaleString() + "\n";
    return true;
  }
  return false;
}

function processArray(obj)
{
  if (obj instanceof Array)
  {
    s += JSON.stringify(obj) + "\n";
    return true;
  }
  return false;
}

function processRegExp(obj)
{
  if (obj instanceof RegExp)
  {
    s += obj.toString() + "\n";
    return true;
  }
  return false;
}

function processVar(obj)
{
  /*
  jelikož každá z funkcí vrací true nebo false na základě typu,
  postupuje proces jednotlivými funkcemi a jakmile narazí na 
  odpovídající typ, provede konverzi na řetězec a díky návratové
  hodnotě true je proces ukončen
  */
  processDate(obj) || processArray(obj) || processRegExp(obj);
}


var x = new Date();
var y = [1, 2, 3];
var z = /asdas/;
processVar(x);
processVar(y);
processVar(z);
alert(s);

      
Guard

Operátoru && se také říká guard, protože často slouží k ochraně před výjimkou (errorem).

Řekněme, že máme proměnnou A, ve které očekáváme konkrétní objektovou strukturu (například je výstupem z funkce, která vrací objekt, nebo null), typ proměnné je potom Object nebo Null, v závislosti, zda daný objekt máme, či nikoliv. A hodláme volat metodu toString daného objektu.

kód 10: Guard
var x = {};
//var x = null;

// můžeme použít podmínku
if (x !== null)
  x.toString();

// můžeme použít guard
x && x.toString();  // toString() se zavolá pouze v případě, že
                    // x není null


// pokud budeme chtít pracovat s výsledkem funkce
var s = '';

// můžeme použít podmínku
if (x !== null)
  s = x.toString();
else
  s = '';

// můžeme použít podmiňovací operátor
s = ((x === null) ? "" : x.toString();


// můžeme použít default a guard
s = (x || "") && x.toString();

      

Guard lze samozřejmě využít i v dalších případech:

kód 11: Guard
// volání metody objektu, pokud ji má
x && x.myMethod && x.myMethod();  // chyba (error) nestane nikdy
                                  // bez ohledu na hodnotu proměnné x


/*
následující příklad nastaví prvnímu elementu PRE barvu na červenou,
pokud takový element není, k volání (b.style.color = 'red') nedojde
*/
var b;
(b = document.getElementsByTagName("pre")[0]) &&
  (b.style.color = 'red');
      
Komentáře: 2 »
  1. Fenix Komentář 24.7.2010 07:16

    Nebude náhodou kód 8 (default)

    17 function A(b)
    18 {
    19 b = b || 1; // nebude-li definováno b, nastaví se 1
    20 // další kód
    21 }

    plnit b hodnotou 1 i v případě, že b bylo nastaveno na 0 nebo prázdný řetězec?

    Odpovědět

Napsat komentář

Diskuze je moderována autorem stránek dle jeho uvážení. Chovejte se tu slušně.