JavaScript

Co byste měli vědět o JavaScriptu [5]: with je zlý čaroděj

Vítejte u dalšího dílu série článku „Co byste měli vědět o JavaScriptu“. K pátemu dílu jsem seriálu nadělil vlastní štítek a také vlastní RSS.

Dnes si povíme o konstrukci with a rovnou prozradím, že učiníte lépe, nebudete-li ji používat.

Konstrukce with

Konstrukce with je určena ke zkrácení zápisu přístupu k vlastnostem objektů.

var osoba = {
    jmeno: "franta",
    prijmeni: "frantiskovec",
    velikostBot: 42
};

//v rámci bloku with mohu pracovat s vlastnostmi
//objektu 'osoba' podobně jako s lokálními proměnnými
with (osoba) {
   //vypíše "franta"
   console.log(jmeno);
   //vypíše "frantiskovec"
   console.log(prijmeni);
   //vypíše odpověď na základní otázku života, vesmíru a vůbec
   console.log(velikostBot);
}

Zkuste si. Vypadá to užitečně, že? Ale třpyt neimplikuje zlato, jak již zajisté víme.

With nepřehledný a zrádný

Představte si, že při čtení JavaScriptového kódu narazíte na následující pasáž:

with (neco) {
    olala = bubu;
}

Poznáte, co uvedený kód dělá? Stát se mohou 4 různé věci, v závislosti na tom, zda jsou olala a bubu vlastnostmi objektu neco.

//olala je vlastností neco, bubu nikoli
neco.olala = bubu;
//bubu je vlastností neco, olala nikoli
olala = neco.bubu;
//bubu i olala jsou vlastnostmi neco
neco.olala = neco.bubu;
//bubu i olala nejsou vlastnostmi neco
olala = bubu;

Vzhledem k dynamické povaze JavaScriptu nemůžete nijak snadno zaručit, že objekt bude mít vámi předpokládané vlastnosti. A pokud je nemá, může zapsaná hodnota snadno skončit v globálním oboru platnosti, což lehce způsobí obtížně odladitelné chyby. Také pokud čtete cízí (nebo vlastní, ale starý) kód a předpoklad existence vlastností není vyjádřen jinak (třeba v komentáři), budete mít nejspíš problém pochopit autorův záměr.

Žijte bez with

With do JavaScriptu bezpochyby nepatří, proto byl ve striktním módu ECMAScriptu 5 vyřazen. Ačkoliv lze dlouze diskutovat o zajímavých použitích této konstrukce, usnadníte si život, pokud se bez něj obejdete i vy.

Co byste měli vědět o JavaScriptu [4]: deklarace funkce a funkce jako výraz

Vítejte u dalšího dílu mého seriálu o méně známých zákoutích JavaScriptu. Pravidelný čtenář si zajisté všiml, že první tři díly měly něco společného. Všechny se nějak dotýkaly platnosti proměnných v JavaScriptu. Dnešní článek nebude výjimkou a bude trochu delší i náročnější, takže doporučuji lehce si osvěžit paměť prolétnutím předcházejících témat.

V prvním díle jsem psal o deklaraci lokálních proměnných, klíčovém slovu var a globálním ‚scope‘, navázal jsem krátkou zmínkou o tom, že v JavaScriptu jsou lokální proměnné platné vždy v rámci celé funkce a nakonec jsem se minulý týden rozepsal o méně známé vlastnosti: variable hoisting.

Continue reading

Další porce zajímavostí kolem JavaScriptu a webu

Ilustrace JavaScript Weekly aneb novinky ze světa Javascriptu každý týden do vašeho emailu. Stojí za odběr, opravdu pěkné odkazy.

Essential JavaScript And jQuery Design Patterns e-book o návrhových vzorech v JS zdarma ke stažení. Rozhodně doporučuji alespoň prolistovat.

Pragmatic Guide to JavaScript nadějně vypadající kniha o Javascriptu (zaznamenal jsem dobré reference). E-book za 13 dolarů a tento pátek ji lze koupit se 40% slevou (sleva by se měla vztahovat na celý sortiment http://pragprog.com)

HTML5 Canvas na serveru? Ale jistě!

Snippet jQuery plugin pro obarvení zdrojových kódů. Interně používá SHJS. Vypadá velice hezky.

Dust.js je sympatický šablonovací engine pro JavaScript (lze použít v prohlížeči, ale třeba i na serveru).

Mathjax je moc hezké knihovna pro zobrazení matematických výrazů (Latex, MathML) na webu. Nic originálního, ale řešení působí lépe než podobné nástroje, se kterými jsem se v minulosti potkal.

Co byste měli vědět o JavaScriptu [3]: variable hoisting

Minule jsem krátce popsal, že v JavaScriptu jsou lokální proměnné platné vždy na úrovni celé funkce, nikoli v bloku. S tím silně souvisí vlastnost, která je v angličtině označována variable hoisting. Rozumný český překlad mě nenapadá (a žádný oficiální neznám), ale sousloví by se dalo kostrbatě přeložit jako „zdvihání proměnných“.

Zdvihám, zdviháš, zdviháme

Princip je jednoduchý: interpret javascriptu při zpracování těla funkce nalezne všechny identifikátory lokálních proměnných deklarovaných pomocí klíčového slova var, a „vyzdvihne“ je na začátek těla funkce (před jakýkoliv příkaz).

Takže následující kód:

function tulipan() {
    if (test()) {
        var promenna = 10;
        fanfan();
    }
    var hodnota = "malá";
    return "vysledek";
    var cislo = 1;
}

Je interpretován jako:

function tulipan() {
    var promenna, hodnota, cislo;
    if (test()) {
        promenna = 10;
        fanfan();
    }
    hodnota = "malá";
    return "vysledek";
    cislo = 1;
}

Proč je to důležité?

Nuže podívejme se na několik ukázek kódu, kde neznalost tohoto principu způsobí vývojaří přinejmenším zmatení.

Přístup ke globální proměnné (či proměnné z nadřazených oborů platnosti):

var hodnota = 20;
function delej() {
    console.log(hodnota);
    var hodnota = 6;
    console.log(hodnota);
}
delej();

Můžete si vyzkoušet, že první volání console.log vypíše undefined a ne 20, jak by mohl očekávat neznalec.

Podobně v následující ukázce bude hodnota proměnné baf uvnitr funcke tulipan vždy vyhodnocena jako „vychozi“.

var baf = 'fanfan';

function tulipan() {
  var baf = baf || 'vychozi';
  console.log(baf);
};

tulipan();

Vyzkoušejte si.

Doporučení na závěr

Běžným doporučením, na které můžete ohledně psaní kódu v JavaScriptu narazit, je právě používání jediného klíčového slova var hned na začátku funkce, kde uvedete všechny lokální proměnné. Pokud k JavaScriptu přijdete z jiného jazyka (jako třeba já z Javy), může to být zarážející. Důvodem je ale právě variable hoisting. Dodržování této rady vám může ušetřit pár nepříjemných záseků.

Příště navážu opět souvisejícím tématem, povíme si něco o deklaracích funkcí.

Co byste měli vědět o JavaScriptu [2]: JavaScript nemá „block-level scope“

V dnešním velice krátkém dílu se zmínim o drobnosti, kterou by měli mít na paměti hlavně programátoři přicházející z jazyků jako je Java či C#. Vývojáře znalé třeba PHP ale zajisté nijak nezaskočí, ti zde budou jako doma. V JavaScriptu (podobně jako v PHP) je totiž lokální proměnná platná vždy v rámci celé funkce.

Oproti tomu ve zmiňované Javě je platnost omezena na blok kódu.

// Java
public void funkce() {
    int  i = 10;
    for (int i =0; i < 15; i++) {
        System.out.println("Uvnitr bloku i: " + i);
    }
    System.out.println("Vne bloku i: " + i);

}

V uvedném kódu překryje proměnná i deklarovaná v záhlaví cyklu vnější proměnnou i.

V Javascriptu ale následující zápis postrádá smysl:

// JavaScript
function funkce() {
    var i = 10;

    for (var i = 0; i < 6; i++) {
        //neco...
    }

    for (var i = 0; i < 68; i++) {
        //neco jineho
    }

}

Proměnná i bude prostě jenom jedna, bez ohledu na počet použití klíčového slova var.

S oborem platnosti na úrovni funkce silně souvisí další zajímavá vlastnost, nazývaná „variable hoisting“. Proberu ji příště.