AÅ¥ jsme sebelepšà programátoÅi, v naÅ¡ich skriptech se nÄkdy vyskytnou chyby. Může se to stát našà vinou, kvůli neoÄekávanému uživatelskému vstupu, chybné odpovÄdi serveru nebo z tisÃce jiných důvodů.
V pÅÃpadÄ chyby skript obvykle âspadneâ (okamžitÄ se zastavÃ) a vypÃÅ¡e chybu na konzoli.
Existuje vÅ¡ak syntaktická konstrukce try...catch, která nám umožÅuje âzachytávatâ chyby, takže skript může mÃsto spadnutà udÄlat nÄco rozumnÄjÅ¡Ãho.
Syntaxe âtryâ¦catchâ
Konstrukt try...catch má dva hlavnà bloky: try a za nÃm catch:
try {
// kód...
} catch (chyba) {
// oÅ¡etÅenà chyby
}
Funguje následovnÄ:
- Nejprve se spustà kód v bloku
try {...}. - Pokud v nÄm nejsou chyby, blok
catch (chyba)je ignorován: bÄh dosáhne koncetry, pÅeskoÄà blokcatcha pokraÄuje dál. - Pokud nastane chyba, výkon bloku
tryse ukonÄà a bÄh pokraÄuje zaÄátkem blokucatch (chyba). PromÄnnáchyba(můžeme ji pojmenovat jakkoli) bude obsahovat chybový objekt s podrobnostmi o tom, co se stalo.
Chyba uvnitÅ bloku try {...} tedy neshodà skript â máme Å¡anci ji zpracovat v bloku catch.
PodÃvejme se na pÅÃklady.
-
PÅÃklad bez chyby: zobrazÃ
alert(1)a(2):try { alert('SpuÅ¡tÄn zaÄátek bloku try'); // (1) <-- // ...zde nejsou žádné chyby alert('SpuÅ¡tÄn konec bloku try'); // (2) <-- } catch (chyba) { alert('Blok catch je ignorován, protože nenastaly žádné chyby'); // (3) } -
PÅÃklad s chybou: zobrazÃ
(1)a(3):try { alert('SpuÅ¡tÄn zaÄátek bloku try'); // (1) <-- lalala; // chyba, promÄnná nenà definována! alert('SpuÅ¡tÄn konec bloku try (nikdy nedosaženo)'); // (2) } catch (chyba) { alert(`Nastala chyba!`); // (3) <-- }
try...catch funguje jen pro bÄhové chybyAby try...catch fungoval, kód musà být spustitelný. Jinými slovy, musà to být platný kód v JavaScriptu.
Nebude fungovat, když bude kód syntakticky nesprávný, napÅÃklad bude obsahovat neuzavÅené složené závorky:
try {
{{{{{{{{{{{{
} catch (chyba) {
alert("Motor tomuto kódu nerozumÃ, kód je nesprávný");
}
JavaScriptový motor nejdÅÃve naÄte kód a pak jej spustÃ. Chyby, které nastanou pÅi fázi naÄÃtánÃ, se nazývajà âpÅekladovéâ (parse-time) chyby a nelze se z nich zotavit (zevnitÅ kódu). Je to proto, že motor takovému kódu nedokáže porozumÄt.
Blok try...catch tedy umà oÅ¡etÅit jen chyby, které se vyskytnou v platném kódu. Takové chyby se nazývajà âbÄhové (runtime) chybyâ nebo nÄkdy âvýjimkyâ.
try...catch funguje synchronnÄJestliže výjimka nastane v ânaplánovanémâ kódu, napÅ. v setTimeout, pak ji try...catch neodchytÃ:
try {
setTimeout(function() {
neexistujÃcÃPromÄnná; // skript tady spadne
}, 1000);
} catch (chyba) {
alert( "nebude to fungovat" );
}
Je to proto, že samotná funkce se spustà pozdÄji, když motor již opustil konstrukt try...catch.
Abychom zachytili výjimku uvnitŠnaplánované funkce, try...catch musà být uvnitŠtéto funkce:
setTimeout(function() {
try {
neexistujÃcÃPromÄnná; // try...catch tuto chybu zpracuje!
} catch {
alert( "zde je odchycena chyba!" );
}
}, 1000);
Chybový objekt
Když nastane chyba, JavaScript vygeneruje objekt obsahujÃcà podrobnosti o této chybÄ. Tento objekt je pak pÅedán jako argument do bloku catch:
try {
// ...
} catch (chyba) { // <-- âchybový objektâ, mÃsto âchybaâ můžeme použÃt jakýkoli název
// ...
}
U vÅ¡ech vestavÄných chyb má chybový objekt dvÄ hlavnà vlastnosti:
name(název)- Název chyby. NapÅÃklad pro nedefinovanou promÄnnou je to
"ReferenceError". message(zpráva)- Textová zpráva o podrobnostech chyby.
Ve vÄtÅ¡inÄ prostÅedà jsou k dispozici i dalšà nestandardnà vlastnosti. Jedna z nejpoužÃvanÄjÅ¡Ãch a nejpodporovanÄjÅ¡Ãch je:
stack(zásobnÃk)- Aktuálnà zásobnÃk volánÃ: ÅetÄzec s informacà o posloupnosti vnoÅených volánÃ, která vedla k chybÄ. PoužÃvá se pro úÄely ladÄnÃ.
NapÅÃklad:
try {
lalala; // chyba, promÄnná nenà definována!
} catch (chyba) {
alert(chyba.name); // ReferenceError
alert(chyba.message); // lalala is not defined
alert(chyba.stack); // ReferenceError: lalala is not defined at (...zásobnÃk volánÃ)
// Můžeme také zobrazit chybu jako celek
// Chyba se pak pÅevede na ÅetÄzec ve tvaru "name: message"
alert(chyba); // ReferenceError: lalala is not defined
}
Objekt chyby v âcatchâ je nepovinný
Pokud nepotÅebujeme podrobnosti o chybÄ, catch ji může vynechat:
try {
// ...
} catch { // <-- bez (chyba)
// ...
}
Použità âtryâ¦catchâ
Prozkoumejme pÅÃpad použità try...catch z reálného života.
Jak už vÃme, JavaScript podporuje metodu JSON.parse(str) k naÄtenà hodnot zakódovaných do JSONu.
Obvykle se použÃvá k dekódovánà dat zÃskaných po sÃti, ze serveru nebo z jiného zdroje.
NaÄteme data a zavoláme JSON.parse následovnÄ:
let json = '{"jméno": "Jan", "vÄk": 30}'; // data ze serveru
let uživatel = JSON.parse(json); // pÅevedeme textovou reprezentaci na objekt JS
// nynà je uživatel objekt s vlastnostmi z ÅetÄzce
alert( uživatel.jméno ); // Jan
alert( uživatel.vÄk ); // 30
PodrobnÄjšà informace o JSON naleznete v kapitole Metody pro JSON, toJSON.
Je-li json poÅ¡kozen, pak JSON.parse vygeneruje chybu, takže skript âspadneâ.
MÄli bychom se s tÃm spokojit? OvÅ¡emže ne!
Pokud je v datech nÄco Å¡patnÄ, tÃmto způsobem se o tom návÅ¡tÄvnÃk nikdy nedozvà (pokud si neotevÅe vývojáÅskou konzoli). A lidé opravdu nemajà rádi, když nÄco âjen tak spadneâ bez jakéhokoli chybového hlášenÃ.
Použijme tedy k oÅ¡etÅenà chyby try...catch:
let json = "{ špatný json }";
try {
let uživatel = JSON.parse(json); // <-- když nastane chyba...
alert( uživatel.jméno ); // nespustà se
} catch (chyba) {
// ...provádÄnà skoÄà sem
alert( "Omlouváme se, v datech byly chyby, pokusÃme se o nÄ požádat jeÅ¡tÄ jednou." );
alert( chyba.name );
alert( chyba.message );
}
Zde použÃváme blok catch jen k zobrazenà zprávy, ale můžeme toho udÄlat mnohem vÃc: poslat nový požadavek po sÃti, nabÃdnout návÅ¡tÄvnÃkovi alternativu, poslat informace o chybÄ na logovacà zaÅÃzenÃ⦠VÅ¡echno je mnohem lepšà než pouhé spadnutÃ.
Vyvolávánà naÅ¡ich vlastnÃch chyb
Co když je json syntakticky správnÄ, ale neobsahuje požadovanou vlastnost jméno?
NapÅÃklad:
let json = '{ "vÄk": 30 }'; // neúplná data
try {
let uživatel = JSON.parse(json); // <-- žádná chyba
alert( uživatel.jméno ); // jméno nenÃ!
} catch (chyba) {
alert( "toto se nespustÃ" );
}
Zde JSON.parse probÄhl normálnÄ, ale absence vlastnosti jméno pro nás ve skuteÄnosti pÅedstavuje chybu.
Abychom sjednotili oÅ¡etÅovánà chyb, použijeme operátor throw.
Operátor âthrowâ
Operátor throw vygeneruje chybu.
Jeho syntaxe je:
throw <chybový objekt>
Technicky můžeme jako chybový objekt použÃt cokoli. Může to být dokonce i primitiv, napÅ. ÄÃslo nebo ÅetÄzec, ale je lepšà použÃvat objekty, pÅednostnÄ s vlastnostmi name a message (abychom zůstali alespoÅ zÄásti kompatibilnà se zabudovanými chybami).
JavaScript obsahuje mnoho vestavÄných konstruktorů pro standardnà chyby: Error, SyntaxError, ReferenceError, TypeError a jiné. I ty můžeme použÃt k vytvoÅenà chybových objektů.
Jejich syntaxe je:
let chyba = new Error(zpráva);
// nebo
let chyba = new SyntaxError(zpráva);
let chyba = new ReferenceError(zpráva);
// ...
Ve vestavÄných chybách (ne ve vÅ¡ech objektech, pouze v chybách) je vlastnost name pÅesný název konstruktoru a message se pÅevezme z argumentu.
NapÅÃklad:
let chyba = new Error("DÄjà se vÄci o_O");
alert(chyba.name); // Error
alert(chyba.message); // DÄjà se vÄci o_O
PodÃvejme se, jaký druh chyby generuje JSON.parse:
try {
JSON.parse("{ špatný json o_O }");
} catch (chyba) {
alert(chyba.name); // SyntaxError
alert(chyba.message); // Unexpected token Å¡ in JSON at position 2
}
Jak vidÃme, je to SyntaxError.
A v naÅ¡em pÅÃpadÄ je absence vlastnosti jméno chyba, jelikož jméno musà mÃt každý uživatel.
Vyvolejme tedy chybu:
let json = '{ "vÄk": 30 }'; // neúplná data
try {
let uživatel = JSON.parse(json); // <-- žádná chyba
if (!uživatel.jméno) {
throw new SyntaxError("Neúplná data: chybà jméno"); // (*)
}
alert( uživatel.jméno );
} catch (chyba) {
alert( "Chyba JSONu: " + chyba.message ); // Chyba JSONu: Neúplná data: chybà jméno
}
Na Åádku (*) operátor throw generuje chybu SyntaxError se zadanou zprávou message, stejným způsobem, jakým by ji vygeneroval samotný JavaScript. Výkon bloku try okamžitÄ skonÄà a bÄh skoÄà do bloku catch.
Nynà se catch stalo jediným mÃstem pro oÅ¡etÅenà vÅ¡ech chyb: jak pro JSON.parse, tak pro jiné pÅÃpady.
OpÄtovné vyvolánÃ
V uvedeném pÅÃkladu jsme použili try...catch ke zpracovánà nekorektnÃch dat. Je vÅ¡ak možné, že uprostÅed bloku try {...} nastane i jiná neoÄekávaná chyba? NapÅÃklad programátorská chyba (promÄnná nenà definována) nebo nÄco jiného, nejenom tahle vÄc s ânekorektnÃmi datyâ.
NapÅÃklad:
let json = '{ "vÄk": 30 }'; // neúplná data
try {
uživatel = JSON.parse(json); // <-- zapomnÄli jsme uvést âletâ pÅed promÄnnou uživatel
// ...
} catch (chyba) {
alert("Chyba JSONu: " + chyba); // Chyba JSONu: ReferenceError: uživatel is not defined
// (ve skuteÄnosti to nenà chyba JSONu)
}
SamozÅejmÄ, vÅ¡echno je možné! ProgramátoÅi dÄlajà chyby. I v utilitách se zveÅejnÄným zdrojovým kódem, které použÃvajà milióny lidà desÃtky let, může být náhle odhalena chyba, která vede ke straÅ¡livým útokům hackerů.
V naÅ¡em pÅÃpadÄ je try...catch použit k tomu, aby zachytil chyby ânekorektnÃch datâ. Ze své povahy vÅ¡ak catch zachytà vÅ¡echny chyby zevnitÅ try. Tady obdržà neÄekanou chybu, ale stále zobrazà stejnou zprávu "Chyba JSONu". To je Å¡patnÄ a ztÄžuje to ladÄnà kódu.
Abychom se takovým problémům vyhnuli, můžeme využÃt techniku âopÄtovného vyvolánÃâ. Pravidlo je jednoduché:
Blok catch by mÄl zpracovávat jen chyby, které zná, a âopÄtovnÄ vyvolatâ vÅ¡echny ostatnÃ.
Techniku âopÄtovného vyvolánÃâ můžeme podrobnÄji vysvÄtlit takto:
- Blok catch zachytà všechny chyby.
- V bloku
catch (chyba) {...}analyzujeme chybový objektchyba. - Pokud jej neumÃme zpracovat, vyvoláme
throw chyba.
Obvykle můžeme ovÄÅit typ chyby operátorem instanceof:
try {
uživatel = { /*...*/ };
} catch (chyba) {
if (chyba instanceof ReferenceError) {
alert('ReferenceError'); // "ReferenceError" kvůli pÅÃstupu k nedefinované promÄnné
}
}
Můžeme také zÃskat název tÅÃdy chyby z vlastnosti chyba.name. Tu majà vÅ¡echny nativnà chyby. Dalšà možnostà je naÄÃst chyba.constructor.name.
V následujÃcÃm kódu můžeme využÃt opÄtovné vyvolánà tak, že catch bude zpracovávat pouze SyntaxError:
let json = '{ "vÄk": 30 }'; // neúplná data
try {
let uživatel = JSON.parse(json);
if (!uživatel.jméno) {
throw new SyntaxError("Neúplná data: chybà jméno");
}
blabla(); // neoÄekávaná chyba
alert( uživatel.jméno );
} catch (chyba) {
if (chyba instanceof SyntaxError) {
alert( "Chyba JSONu: " + chyba.message );
} else {
throw chyba; // opÄtovné vyvolánà (*)
}
}
Chyba vyvolaná na Åádku (*) zevnitÅ bloku catch âvypadneâ z bloku try...catch a buÄ může být zachycena vnÄjÅ¡Ãm konstruktem try...catch (pokud existuje), nebo shodà skript.
Blok catch tedy ve skuteÄnosti oÅ¡etÅà jen chyby, s nimiž si umà poradit, a vÅ¡echny ostatnà âpÅeskoÄÃâ.
NásledujÃcà pÅÃklad pÅedvádÃ, jak lze takové chyby zachytit dalšà úrovnà try...catch:
function naÄtiData() {
let json = '{ "vÄk": 30 }';
try {
// ...
blabla(); // chyba!
} catch (chyba) {
// ...
if (!(chyba instanceof SyntaxError)) {
throw chyba; // opÄtovné vyvolánà (neumÃme si s nà poradit)
}
}
}
try {
naÄtiData();
} catch (chyba) {
alert( "VnÄjšà catch zachytil chybu: " + chyba ); // chytili jsme ji!
}
Zde funkce naÄtiData umà oÅ¡etÅit jedinÄ SyntaxError, zatÃmco vnÄjšà try...catch umà oÅ¡etÅit vÅ¡echno.
tryâ¦catchâ¦finally
PoÄkat, to jeÅ¡tÄ nenà vÅ¡echno.
Konstrukt try...catch může mÃt jeÅ¡tÄ jednu kódovou klauzuli: finally.
Pokud existuje, spustà se ve vÅ¡ech pÅÃpadech:
- po
try, pokud nenastaly žádné chyby, - po
catch, pokud nastaly chyby.
RozÅ¡ÃÅená syntaxe vypadá následovnÄ:
try {
... pokusÃme se spustit kód ...
} catch (chyba) {
... oÅ¡etÅÃme chyby ...
} finally {
... toto se vždy spustà ...
}
Zkuste si spustit tento kód:
try {
alert( 'try' );
if (confirm('Vyvolat chybu?')) CHYBNÃ_KÃD();
} catch (chyba) {
alert( 'catch' );
} finally {
alert( 'finally' );
}
Tento kód může bÄžet dvÄma možnými cestami:
- Pokud odpovÃte âAnoâ na âVyvolat chybu?â, pak
try -> catch -> finally. - Pokud odpovÃte âNeâ, pak
try -> finally.
Klauzule finally se Äasto použÃvá, když zaÄneme nÄco dÄlat a chceme to ukonÄit, aÅ¥ je výsledek jakýkoli.
NapÅÃklad chceme zmÄÅit Äas, jaký spotÅebuje funkce fib(n) pro výpoÄet Fibonacciho ÄÃsel. PÅirozenÄ můžeme zahájit mÄÅenà pÅedtÃm, než se spustÃ, a ukonÄit je posléze. Co když vÅ¡ak bÄhem volánà funkce nastane chyba? KonkrétnÄ implementace fib(n) v následujÃcÃm kódu vrátà chybu pro záporná nebo necelá ÄÃsla.
Klauzule finally je vhodné mÃsto, v nÄmž můžeme ukonÄit mÄÅenÃ, aÅ¥ funkce dopadne jakkoli.
Zde finally zaruÄuje, že Äas bude správnÄ zmÄÅen v obou situacÃch â v pÅÃpadÄ ÃºspÄÅ¡ného spuÅ¡tÄnà fib i v pÅÃpadÄ, že bÄhem nÄj nastane chyba:
let ÄÃslo = +prompt("Zadejte kladné celé ÄÃslo", 35)
let rozdÃl, výsledek;
function fib(n) {
if (n < 0 || Math.trunc(n) != n) {
throw new Error("ÄÃslo nesmà být záporné a musà být celé.");
}
return n <= 1 ? n : fib(n - 1) + fib(n - 2);
}
let zaÄátek = Date.now();
try {
výsledek = fib(ÄÃslo);
} catch (chyba) {
výsledek = 0;
} finally {
rozdÃl = Date.now() - zaÄátek;
}
alert(výsledek || "nastala chyba");
alert( `výkon funkce trval ${rozdÃl} ms` );
Můžete si to ovÄÅit, když spustÃte kód a do prompt zadáte 35 â spustà se normálnÄ, finally pÅijde po try. A pak zadejte -1 â okamžitÄ nastane chyba a výkon funkce bude trvat 0 ms. ObÄ mÄÅenà probÄhla správnÄ.
Jinými slovy, funkce může skonÄit pomocà return nebo throw, na tom nezáležÃ. Klauzule finally se spustà v obou pÅÃpadech.
try...catch...finally jsou lokálnÃProsÃme vÅ¡imnÄte si, že promÄnné výsledek a rozdÃl v uvedeném kódu jsou deklarovány pÅed try...catch.
Jinak kdybychom deklarovali let v bloku try, promÄnné by byly viditelné jen uvnitÅ bloku.
finally a returnKlauzule finally funguje pÅi jakémkoli opuÅ¡tÄnà bloku try...catch. To platà i pro výslovnÄ uvedený return.
V následujÃcÃm pÅÃkladu je return uvnitÅ try. V tom pÅÃpadÄ se finally spustà právÄ pÅedtÃm, než se bÄh vrátà do vnÄjÅ¡Ãho kódu.
function funkce() {
try {
return 1;
} catch (chyba) {
/* ... */
} finally {
alert( 'finally' );
}
}
alert( funkce() ); // nejprve se spustà alert z finally a pak tento
try...finallyKonstrukt try...finally je užiteÄný i bez klauzule catch. PoužÃváme jej, když zde nechceme oÅ¡etÅovat chyby (necháme je vypadnout ven), ale chceme mÃt jistotu, že procesy, které jsme zahájili, budou dokonÄeny.
function funkce() {
// zaÄneme dÄlat nÄco, co musÃme dokonÄit (napÅ. mÄÅenÃ)
try {
// ...
} finally {
// dokonÄÃme to, i když vÅ¡echno spadne
}
}
V uvedeném kódu chyba vzniklá uvnitÅ try vždy vypadne, protože zde nenà catch. Ale finally se vykoná jeÅ¡tÄ pÅedtÃm, než bÄh opustà funkci.
Globálnà zachycenÃ
Informace z této Äásti nejsou souÄástà jádra JavaScriptu.
PÅedstavme si, že jsme zÃskali fatálnà chybu mimo try...catch a skript spadl. NapÅÃklad programátorskou chybu nebo nÄco jiného straÅ¡ného.
Existuje způsob, jak na takové výskyty reagovat? Můžeme chtÃt chybu zalogovat, zobrazit nÄco uživateli (ten obvykle chybové zprávy nevidÃ) a podobnÄ.
Ve specifikaci žádný nenÃ, ale prostÅedà jej obvykle poskytujÃ, protože je opravdu užiteÄný. NapÅÃklad Node.js má k tomuto úÄelu process.on("uncaughtException"). A v prohlÞeÄi můžeme pÅiÅadit speciálnà vlastnosti window.onerror funkci, která se spustà v pÅÃpadÄ nezachycené chyby.
Syntaxe:
window.onerror = function(zpráva, url, Åádek, sloupec, chyba) {
// ...
};
zpráva- Chybová zpráva.
url- URL skriptu, v nÄmž doÅ¡lo k chybÄ.
Åádek,sloupec- ÄÃslo Åádku a ÄÃslo sloupce, v nichž chyba nastala.
chyba- Chybový objekt.
NapÅÃklad:
<script>
window.onerror = function(zpráva, url, Åádek, sloupec, chyba) {
alert(`${zpráva}\n Na ${Åádek}:${sloupec} adresy ${url}`);
};
function naÄtiData() {
Å¡patnáFunkce(); // Ouha, nÄco se pokazilo!
}
naÄtiData();
</script>
Ãkolem globálnÃho handleru window.onerror obvykle nenà obnovit bÄh skriptu â to je v pÅÃpadÄ programátorských chyb už zÅejmÄ nemožné, ale poslat vývojáÅům chybovou zprávu.
Existujà i webové služby, které poskytujà logovánà chyb pro tyto pÅÃpady, napÅÃklad https://www.muscula.com nebo or https://www.sentry.io.
Fungujà následovnÄ:
- Zaregistrujeme se na službÄ a dostaneme od nà kousek kódu v JS (nebo URL skriptu), který si vložÃme na stránku.
- Skript v JS nastavà uživatelskou funkci
window.onerror. - Když nastane chyba, skript poÅ¡le službÄ sÃÅ¥ový požadavek s informacà o chybÄ.
- Pak se můžeme pÅihlásit na webové rozhranà služby a chyby si prohlédnout.
ShrnutÃ
Konstrukt try...catch nám umožÅuje oÅ¡etÅovat bÄhové chyby. Doslova nám umožÅuje âpokusit seâ (anglicky âtryâ) spustit kód a âzachytitâ (anglicky âcatchâ) chyby, které v nÄm mohou nastat.
Syntaxe je:
try {
// spustà se tento kód
} catch (chyba) {
// pokud nastala chyba, skoÄÃ se sem
// v promÄnné chyba je chybový objekt
} finally {
// toto se provede v každém pÅÃpadÄ po try/catch
}
Sekce catch nebo finally tam nemusà být, takže fungujà i kratšà konstrukty try...catch a try...finally.
Chybové objekty majà následujÃcà vlastnosti:
messageâ chybová zpráva Äitelná ÄlovÄkem.nameâ ÅetÄzec s názvem chyby (název konstruktoru chyby).stack(nestandardnÃ, ale Å¡iroce podporovaná) â zásobnÃk v okamžiku vzniku chyby.
Pokud chybový objekt nepotÅebujeme, můžeme jej vynechat a použÃt jen catch { namÃsto catch (chyba) {.
Můžeme také generovat své vlastnà chyby pomocà operátoru throw. Technicky může být argumentem throw cokoli, ale obvykle to je chybový objekt zdÄdÄný z vestavÄné tÅÃdy Error. O rozÅ¡iÅovánà chyb se dozvÃme vÃce v pÅÃÅ¡tà kapitole.
Velmi důležitým vzorcem oÅ¡etÅovánà chyb je opÄtovné vyvolánÃ: blok catch obvykle oÄekává a umà oÅ¡etÅit jen chyby urÄitého typu, takže chyby, které nezná, by mÄl opÄtovnÄ vyvolat.
I když nemáme try...catch, vÄtÅ¡ina prostÅedà nám umožÅuje nastavit âglobálnÃâ chybový handler, který bude zachytávat chyby, které âvypadnouâ. V prohlÞeÄi je to window.onerror.
KomentáÅe
<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â¦)