Debugging v javascriptu aneb alert() není to pravé
17. 12. 2010 -
O objektu console a jeho použití ve spojení s Firebugem.
Všichni už jsme se určitě setkali s tím, že jsme při psaní nějakého skriptu potřebovali zjistit, jakou hodnotu nám daná funkce vrací či jakou hodnotu má, v určitou chvíli, nějaká proměnná. Myslím si, že určitě znáte a pravděpodobně i používate pro tyto situace alert(), který hodnotu prostě vyhodí do dialogového okna. Je ale správné alert() takhle „zneužívat“? V některých případech se asi jinému použití nevyhneme. Existuje však objekt konsole, který je pro tyto případy uzpůsoben.
Console je objekt, který zapisuje do konzole Prohlížeče (v našem případě konzole Firebugu ve Firefoxu - ten má drtivá většina vývojářů nainstalován) údaje, které bychom si jinak promítali právě alertem. Nejen, že má konsole spoustu vlastností, které se dají použít k různým věcem, aniž bychom museli předtím něco extrémně připravovat pro vyhození hlášky alertem. Je to také velmi elegantní řešení. Představme si, že se do scriptování ponoříme natolik, že vznikne obrovský shluk funkcí a objektů. Při jejich vývoji jsme si pomáhali právě alertem. Po dokončení se musí všechny skripty znova projít a zkontrolovat, zda nám někde nezůstal schovaný nějaký „debug“ alert, který by případně na produkci dělal neplechu. Ono by asi nebylo dobré, kdyby návštěvníkovi stránek při procházení stránky podpořené JavaScriptem, při nějakém kliku vyskakovala „divná hláška“ s nějakým číslem, či shlukem nějakých znaků. Toto se nám u objektu console stát nemůže.
Představme si tedy, co objekt console vlastně umí a jak se dá skvěle využít i například k logování složitějších javascriptových funkcí. Nejprve si však ukážeme, kde vůbec hledat konzoli Firebugu, a jak jí používat.
Firebug konzole
Konzole ve Firebugu má spoustu možností zobrazení různých objektů. Záleží na každém, co si zapne pro debugování.

Základní vzhled konzole ve Firebugu 1.6.0.
záložka Errors (červeně) zobrazí pouze errorové hlášky
záložka Warnings (žlutě) zobrazí pouze varování
záložka Info (modře) zobrazí pouze informace
a záložka Debug Info (zeleně) zobrazí pouze debugovací informace
Na konzoli je také velice zvláštní tlačítko "profilovat", ke kterému se také někdy dostaneme. Dnes ale není na pořadu dne (třeba někdy příště).
Jak už bylo zmiňováno, JavaScript má objekt console, pomocí kterého můžeme do konzole zapisovat. Představíme si tedy, jakým způsobem můžeme konzoli využít.
Vlastnosti objektu console
console.log([object], [String]);
Pomocí tohoto můžeme zapisovat log do konzole, kde [object] je jakýkoliv objekt ve stránce, na který se nám v logu vytvoří hypertextový odkaz.
console.log("Rozlišení obrazovky: "+screen.width+" x "+screen.height+"px");
výsledek vypadá takto:

Ještě jeden případ s odkazem na objekt:
console.log(document.getElementById("test"),"Velikost objektu: "+document.getElementById("test").offsetWidth+" x "+document.getElementById("test").offsetHeight+"px");

console.info([object], [String]);
Info nám zapisuje informaci s Ikonkou a podbarvením určenými pro informaci.
console.info("Vysledek 1+4="+(1+4));
console.warn([object], [String]);
Warn zapisuje výstrahu s Ikonkou a podbarvením.
console.warn("Cyklus for prekrocil 100 otoceni.");
console.error(object, [String]);
Error zapisuje chybu, opět s Ikonkou a podbarvením, navíc s výstrahou do statusu lišty. U erroru musí být uveden objekt, i když to může být prázdná hodnota.
console.error("","Na strance se vyskytla chyba");
console.error(document.getElementById("test"),"Objekt nema spravne parametry.");
a výsledek:

console.debug([object], [String])
Vypíše hlášku do debug modu.
console.debug("Zapisuji debug.");
console.clear();
Vymaže konzoli.
Pozn.: Tento výraz nedoporučuji příliš využívat. Umožní totiž zpřehlednit části, ale také může schovat jiné chyby, které se během provádění skriptu na stránce vyskytly.
Tolik k vlastnostem, které nám vypisují nějaké hlášky. Objekt console má totiž také vlastnosti, které jsou spíše funkční.
Začněme něčím jednoduchým, co nám spíše pomůže zpřehlednit vypisování do konzole a je zároveň přínosným nástrojem pro debugování jednotlivých celků skriptu.
console.group([object], [String]);
console.groupEnd();
Tyto vlastnosti umožňují rozdělit si určité části v konzoli do jednotlivých bloků. Pokud tedy máme více funkcí, ve kterých používáme stejnou hlášku, např.: „for se otočil x krát.“, můžeme je přehledně rozdělit do skupin, do kterých náleží. Skupiny mohou být i vnořené, lze tedy rozdělovat i větší bloky na menší, atp.
console.info("Za touto hláškou spustím založení skupiny.");
console.group("Testovací skupina");
console.log("Text uvnitř skupiny.");
console.warn("Upozornění uvnitř skupiny");
console.group("Podskupina skupiny Testovací");
console.log("Text uvnitř podskupiny.");
console.error("","Nastala chyba uvnitř podskupiny");
console.groupEnd();
console.info("Uzavřel jsem podskupinu skupiny Testovací.");
console.groupEnd();
console.info("Uzavřel jsem Testovací skupinu.");
výsledek:

console.time(name);
console.timeEnd(name);
Vlastnost time umožňuje spočítat si čas, který uběhne od nějaké události ke druhé. Povinný parametr name dává časovači název, podle kterého ho poté konzole rozpozná a vypíše. Při ukončování musíme opět uvést jméno časovače, který chceme zastavit, protože různé časovače se mohou prolínat.
console.time("Načtení stránky");
console.info("Za touto hláškou spustím založení skupiny.");
console.group("Testovací skupina");
console.log("Text uvnitř skupiny.");
console.warn("Upozornění uvnitř skupiny");
console.groupEnd();
console.info("Uzavřel jsem Testovací skupinu.");
console.timeEnd("Načtení stránky");
výsledek:

console.profile([String]);
console.profileEnd();
Na začátku jsem sliboval, že se podíváme blíže na tlačítko "profilovat", a je to tu. Samotné tlačítko nás až tolik zajímat nebude. Budeme se spíše věnovat vlastnosti objektu console, která provádí tu samou funkci. Má však velkou výhodu v tom, že jí ukončíte přesně v tu chvíli, kdy chcete. Profilování může na stránce běžet jen jednou v danou chvíli, tudíž není u ukončovací vlastnosti žádný parametr. Profilování jednoduše provede porovnání vytížení systému na jednotlivé funkce a zobrazí i další údaje, jako např. čas provádění funkce (pokud je funkce volaná vícekrát, tak zobrazí i min a max čas), atp.
console.profile("Profil 1");
function testFor() {
for (x = 0; x <= 100; x++) {
document.write(x+"<br />");
}
})();
console.profileEnd();
výsledek:

console.dirxml(node)
Zobrazí v konzoli celý HTML daného uzlu.
<div id="test">aaabbb<br />cccddd</div>
<script type="text/javascript">
console.dirxml(document.getElementById("test"));
</script>
výsledek:

console.dir(object)
Zobrazí vlastnosti objektu uvedeného v parametru. Tyto vlastnosti se dají také najít na záložce DOM.
console.dir(console);
Výsledek:

console.count([String]);
Vypíše do konzole, kolikrát bylo během provádění JavaScriptu voláno count(). Pokud je voláno více countů najednou, je potřeba si je pojmenovat, aby konzole věděla, kam co má přičítat.
for (x=0;x<100;x++){
console.count("Otoceni for");
}
výsledek:

console.table(data);
Jedna z nejužitečnějších věcí, které console nabízí. Table dává možnost přehledně a hlavně variabilně zobrazit údaje (data) objektů u předaného objektu či pole. Pokud má objekt velké množství objektů, můžeme si nechat vypsat jen nějaké, pomocí konstrukce:
console.table(team,[vlastnost, vlastnost, vlastnost,…]);
Pokud tedy nevydefinujeme vlastnosti, zobrazí se nám náhled se všemi vlastnostmi.
Při zadání:
var team = new Array();
team[0] = {
jmeno: 'Josef',
prijmeni: 'Krasny',
pozice: 'utok',
vek: 39,
cislo: 10,
bydliste: 'Praha'
};
team[1] = {
jmeno: 'Alois',
prijmeni: 'Moucka',
pozice: 'obrana',
vek: 28,
cislo: 4,
bydliste: 'nezname'
};
team[2] = {
jmeno: 'Pert',
prijmeni: 'Vorel',
pozice: 'brankář',
vek: 31,
cislo: 1,
bydliste: 'Plzeň'
};
team[3] = {
jmeno: 'František',
prijmeni: 'Bezda',
pozice: 'záloha',
vek: 27,
cislo: 6,
bydliste: 'Praha'
};
console.group("Fotbalový tým obce");
console.table(team,["prijmeni", "jmeno", "vek", "pozice"]);
console.groupEnd();
výsledek:

Jak je vidět na obrázku, Firebug nám v konzoli zobrazí pouze vydefinované vlastnosti (v našem případě: prijmeni, jmeno, vek, pozice) objektů uložených v poli. Lze si také všimnout, že výsledná tabulka dovoluje, podle zvolených vlastností, sortovat (vzestupně/sestupně) a umožňuje nám se tak lépe zorientovat.
Důležité
Velmi důležité je volat vlastnosti objektu console jen tam, kde jsou dostupné. Objekt console je totiž podporován i v ostatních Prohlížečích (ne ve všech), ale ty nedisponují takovým množstvím vlastností, jako právě ve Firebugu. Je tedy nutné, předtím než se vůbec začne objekt používat, ocheckovat si, zda-li je objekt vůbec podporován, či zda jsme v Prohlížeči s nainstalovaným Firebugem.
Nejjednodušší způsob je asi tento:
if (console.firebug) {
… [volani objektu console] …
}
Pokud ovšem nepoužíváme volání objektu console jen na jednom místě, nastává problém. Checkovat objekt před každým voláním je dost děsivé, a proto není špatné někde na začátku skriptu si vytvořit objekt, který bude založen na objektu console a bude mít stejné vlastnosti, které ve skriptu používáme.
var debug = new Object({
log: function(){},
debug: function(){},
info: function(){},
warn: function(){},
error: function(){},
clear: function(){},
dir: function(){},
dirxml: function(){},
group: function(){},
groupEnd: function(){},
time: function(){},
timeEnd: function(){},
profile: function(){},
profileEnd: function(){},
count: function(){},
table: function(){}
});
if (window.console) {
if (console.firebug) {
debug = console;
}
}
Závěrem
Objekt console je tedy určen vývojářům JavaScriptu, kteří využívají alert() pro debugování svých skriptů. Jeho použití je jednodušší, efektnější a hlavně elegantnější – zkrátka posune vývoj JavaScriptu o něco výš. Využití objektu console jsou nepřeberné a proto by nebylo špatné zamyslet se třeba nad tím, jestli by se objekt console nedal využít i pro logování složitějších JavaScriptů. Když se poté vrátíme ke skriptu, kde se vyskytla chyba, hned ve Firebugu zjistíme, ve kterých místech skript zatuhnul, či spadl. Návštěvníkovi stránek se nic zobrazovat nebude. Pokud ale návštěvníkem stránek bude člověk z oboru, naopak ho může nadchnout řešení debugování JavaScriptu, kde v konzoli Firebugu bude mít popsáno, co se v danou dobu děje. (Např.: Probíhá načítání objektů. Načítání objektů bylo dokončeno. atp.) Samozřejmě, že narazíme i na části, kde se použití alertu nevyhneme (ale i u těch se dá alert nahradit objektem console). Teď už se jen musíme naučit tyto nástroje, jako například právě objekt concole využívat, a při skriptování místo alertu používat třeba console.log().
Zdroje:
Console API - http://getfirebug.com/wiki/index.php/Console_API
Tabular logs in Firebug - http://www.softwareishard.com/blog/firebug/tabular-logs-in-firebug/
Firebug´s console.profile vs console.time - http://www.stoimen.com/blog/2010/02/03/firebugs-console-profile-vs-console-time/
Další články autora:
-
Kouzla SVG a VML – dynamická grafika na webu - 6. 9. 2011
Určitě všichni už se na webech někdy setkali s těmito možnostmi zobrazení vektorové grafiky. U SVG jmenujme třeba grafy, které nejsou tvořeny Flashem. VML nachází hojné využití například v Microsoft Office. Pojďme si obě zkratky představit blíže.
-
Kouzla SVG a VML – použití JavaScriptí knihovny jMGFX - 10. 10. 2011
Jak už jsem v předchozím článku psal, vytvořil jsem vlastní knihovnu, která je volně k šíření a použití.
Pošli článek na: