# Časté potíže

Odkazujte prosím na konkrétní kotvy (#), ne na čísla příspěvků.

# Součet čísel versus součet řetězců

Vezmete-li např. hodnotu z textového<input>u, skript s ní pracuje jako s řetězcem, i když je v ní vepsané číslo. Pokud k ní něco přičtete, výsledkem bude pořád řetězec, z "1" + 5 vyjde "15", nikoliv 6. Dosáhnout číselného součtu jde několika způsoby:
• Vynásobit řetězec jedničkou: proměnná * 1 + 5.
• Místo přičtení odečíst zápornou hodnotu: -(-proměnná) + 5.
• Přičíst kladnou hodnotu: +proměnná + 5.
• Použít funkci Number: Number(proměnná) + 5.
• Použít funkci parseFloat či parseInt: parseFloat(proměnná) + 5

# Detekce číselné soustavy v parseIntu

Funkce parseInt umí být tak chytrá, až to někdy není hezké. Dokáže zpracovávat zápisy čísel v různých číselných soustavách. Soustavu může programátor určit druhým argumentem, parseInt("11111011010", 2) vrátí 2010, parseInt("BADF00D", 16) vrátí 195948557 atd. — pokud ovšem není druhý argument uvedený, funkce se pokusí uhodnout soustavu podle konvencí zápisu čísel v JS. Což znamená, že:
parseInt("11") vrátí 11, jelikož předpokládá desítkovou soustavu,
parseInt("0x11") vrátí 17, jelikož předpokládá šestnáctkovou soustavu,
parseInt("011") vrátí v některých prohlížečích 9, jelikož předpokládá osmičkovou soustavu,
parseInt("08") vrátí v některých prohlížečích 0, jelikož předpokládá osmičkovou soustavu a v té číslice „8“ neexistuje — na tohle pozor. V Opeře vám tato chyba projde.
Chcete-li se vyhnout autodetekci soustavy, vždy uvádějte druhý argument.

# Uchování hodnot proměnných v anonymních funkcích — lexikální uzávěry

Pokud vytváříte v cyklu timeouty nebo přiřazujete obsluhu události a potřebujete uvnitř vnitřní funkce pracovat s hodnotou proměnné cyklu, které nabývala v okamžiku vytvoření vnitřní funkce, musíte použít lexikální uzávěr. Názorněji:
Zbavení se kontextu (odkazu, provázání…) s proměnnou
Změna proměnné při načtení obrázku
Zajímavost — je to ekvivalentní kód?
Anonymní funkce a uzávěry

# Nepoužívejte eval, ani jeho obdoby

Používání eval, a jeho ekvivalentů, tedy new Function, setInterval(řetězec, číslo) a setTimeout(řetězec, číslo) je velké zlo (z anglického eval is evil). Psát jakýkoliv kód jako řetězec a pak ho spouštět vyhodnocením je velmi nebezpečné. Můžou tím snadno vzniknout chyby, které se velmi těžko hledají. V 99 % případů* to ukazuje na špatný návrh aplikace a je to zbytečné.“ — Tak pravil kolega ah01 a měl svatou pravdu. JavaScript je stavěný tak, aby programátor při běžné práci eval nepotřeboval. Lidé tu funkci používají z neznalosti rozumnějších postupů, vytvářejí tím nevýkonný a nebezpečný, ale hlavně méně přehledný a hůř udržovatelný kód. Obvykle narážejí na praktické problémy s (ne)escapováním uvozovek a s předáváním argumentů, které nejsou vyjádřitelné řetězcem.
Funkcím setInterval a setTimeout dávejte jako první argument přímo funkci:
setTimeout(function() { alert("Baf!"); }, 5000);
setTimeout(bafnout, 5000);   // máte-li nějakou funkci jménem „bafnout“
Potřebujete-li změnit hodnotu vlastnosti objektu, jejíž jméno máte v proměnné, také nepotřebujete eval.
*) Zbývá 1 % specifických případů, kdy se eval skutečně vyplatí používat, protože všechno zlé může být k něčemu dobré. Ale pokud vás někdo odkázal sem, ten váš případ to není.

# Rozdíl mezi voláním funkce a funkcí

JavaScript, na rozdiel od niektorých iných programovacích jazykov, môže pracovať s funkciou ako s dátovým typom. Výraz f() znamená operátor volania funkcie aplikovaný na premennú f. Jeho výsledkom je buď hodnota vrátená príkazom return vo funkcii, alebo špeciálna hodnota undefined. Výraz f je tá funkcia samotná, ktorá môže byť uložená do inej premennej, predaná ako parameter pri volaní inej funkcie a podobne. (Zformuloval _es.)
Názorně:
function kousnout()
{
  if(confirm("Chceš kousnout?")) Zuby.kousnoutNávštěvníka();
}
dezert.onclick = kousnout();  // tím přiřadíte výsledek funkce kousnout (= undefined), která se v okamžiku přiřazení zavolá, většinou nežádoucí!
dezert.onclick = kousnout;    // tím přiřadíte funkci kousnout, která se zavolá až při kliknutí na dezert
window.onload = alert("Ahoj.");  // alert vyskočí hned při přiřazení, do onload se dá undefined
window.onload = function() { alert("Ahoj."); };  // alert vyskočí až při události onload
Samozřejmě, že i návratovou hodnotou funkce může být funkce, ale to není příliš obvyklý scénář.

# Dvojí přístup ke členu (vlastnosti/metodě) objektu

Zápisy objekt.vlastnost a objekt["vlastnost"] jsou ekvivalentní. Pokud se v názvu člena vyskytují znaky, které nejsou dovoleny v názvu identifikátoru (třeba „-“ či „[]“), je druhý zápis jedinou možností, jak se k dotyčnému členovi dostat. Mějme třeba tento kód:
<form name="vyber-cilu">
  <input type="checkbox" name="planety[]" value="Dantooine"> Dantooine
  <input type="checkbox" name="planety[]" value="Alderaan"> Alderaan
  <input type="checkbox" name="planety[]" value="Yavin IV"> Yavin IV
</form>
Kdybychom chtěli zjistit, zda je zaškrtnutý Alderaan, použijeme document["vyber-cilu"]["planety[]"][1].checked.
Zápis s řetězcem také umožňuje dostat se ke členovi, jehož název máte uložený v proměnné.

# Výsledkem výpočtu 1 - 0.9 není přesně 0.1

Na stejný problém narazíte prakticky ve všech programovacích jazycích — je zapříčiněn reprezentací reálných čísel v paměti (kdo by měl zájem, zde je bližší vysvětlení).
javascript nevie pocitat
odchylka pri real (v kategorii PHP)
math.floor chybne vypočítava

# Používejte var

Příkaz var deklaruje proměnnou v kontextu funkce, v níž je použit, nebo v globálním kontextu. Užívá se snadno:
var hrnecku = "kaši";
var počet = 5, nespočet = 6;
for(var i = 0; i < počet; i++) { … }
Rozhodnete-li se navzdory doporučením vynechat var, musíte počítat s několika úskalími:
• Všechny takto vytvořené proměnné jsou globální, a tudíž si mohou např. různé cykly v různých funkcích užívající tutéž iterační proměnnou jménem i lézt do zelí.
• Nemůžete z nedeklarované proměnné číst dřív, než do ní zapíšete — vyskočila by na vás chyba, nikoliv roztomilé undefined.
• Nedeklarovanou proměnnou je možné smazat operátorem delete.
• Některé názvy proměnných mohou kolidovat s nativními vlastnostmi globálního objektu (tj. window).
• Přiřazení do nedeklarované proměnné může vyvolat chybu v některých prohlížečích, pokud v dokumentu existuje element se shodným atributem id či name.
… navazuje na Časté potíže výše. Odkazujte prosím na konkrétní kotvy (#), ne na číslo příspěvku.

# Psaní metodou document.write po načtení stránky maže stránku

Pokoušíte se vypsat něco pomocí document.write v reakci na onclick či jinou událost? Prohlížeče vás určitě nepotěší. Jakmile je stránka načtená, document je uzavřený a jakýkoliv pokus o další zápis způsobí, že se založí nový dokument a píše se do něj. Kam si myslíte, že by se mělo psát?

• Chcete změnit vnitřní HTML nějakého elementu?
document.getElementById("ídéčko").innerHTML = "<b>Ahoj světe!</b>";
• Nebo chcete změnit value formulářového prvku?
document.jménoFormuláře.jménoPrvku.value = "Ahoj světe!";
• Nebo si chcete jen pro účely testování vypsat nějakou hodnotu?
alert("Ahoj světe!");  // vyskočí dialogové okno, čeká na odkliknutí
document.title = "Ahoj světe!";  // změní titulek stránky, nečeká na odkliknutí

# Problémy se setAttribute/getAttribute

V řadě prohlížečů nefungují dokonale metody setAttribute a getAttribute, proto doporučuji používat standardní vlastnosti HTML DOMu.

# Práce s klávesnicí a dalšími vstupy

Navigace šipkami na klávesnici
ASCII kurzorových šipek — o lapáliích s onkeypress, charCode apod.
Odchycení gesta na mobilu?

# Hrátky s focusem

událost po kliknutí na textbox — vyčištění formulářového políčka při focusu
Kurzor v inputu hned po načtení stránky
• Pěkný návod na práci s pozicí kurzoru v <textarea> napsal los.



# Potíže s frameworky, jQuery apod.

Většina potíží, které se zdánlivě týkají frameworků, pramení z neznalosti výše popsaných základních principů JavaScriptu a fungování prohlížečů.
Na živé ukázky skutečných potíží s jQuery se hodí jQuery zkoušečka od ah01.

# Co vlastně je jQuery?

Celé jQuery je jen jedna docela obyčejná (ačkoliv velká) javascriptová funkce/objekt s množstvím malých metod. Není to žádná zbrusu nová zázračná technologie podporovaná novými prohlížeči, jen jiný způsob využití toho, co už je v JavaScriptu dostupné posledních deset let. Neumí nic, co by neuměl samotný JavaScript, nemůže být rychlejší než JavaScript, nemá lepší/horší syntaxi než JavaScript, protože jQuery není nic než JavaScript.

# Jak fungují frameworky?

jQuery - základní kostra zdrojového kódu
prototype.js > nedostatečně optimalizovaný kód
Propašování nové funkce k prototypu libovolného elementu
Sexy dolar
Názor na můj framework Legio

# Kontroverzní případy použití frameworku

Část lidí na této diskusi nesdílí všeobecné nadšení z javascriptových frameworků a na pokusy zatáhnout závislost na jQuery absolutně všude reaguje pohoršeně, což vede k více či méně zajímavým konfrontacím.
AJAX, spuštění php souboru
Po načtení spustit funkci
Hodnota checkboxu vytoreneho AJAXOM
Prolnutí stránek ajaxem
jQuery - Přidání kódu s přidanými událostmi
Jak nechat skrýt určitý text za 5 s?
Složitější manipulace s CSS v JS



# Zajímavosti a poučné dotazy

Hádanka — o typových konverzích.
Rozdily ve verzich Javascriptu — o anomáliích v implementacích JS.
Jak dobře znáte JavaScript - předveďte se [kvíz]
window.name, name, var name, teoretické zaujímavosti
Rychlost načtení javascriptu odděleného od html — polemika o vhodném umístění skriptů ve stránce.
Cyklus k vlastnostiam objektu Math?
Rozdíl mezi setInterval a setTimeout
Úklid paměti, zrušení provázanosti objektů, garbage collector
Zábavné chvilky s klíčovým slovem "this"
Sporná náhodnost náhodného míchání sortem

# JavaScript není Java

JavaScript je nejpoužívanější oficiální přezdívka ECMAScriptu, dynamického slabě typového programovacího jazyku s objektovým programováním založeným na prototypech. Používá se jako skriptovací jazyk převážně v prohlížečích. Jeho pokrevní bratr ActionScript se užívá ve Flashi.
Java je jméno platformy a statického silně typového programovacího jazyku s objektovým programováním založeným na třídách. Používá se převážně v mobilních telefonech. (Java applety se užívají v prohlížečích, ale jde o dlouhodobě umírající větev vývoje.)
• JavaScript má pár vnitřních tříd a metod nazvaných stejně jako Java, oba jazyky vycházejí z Céčka a oba mají v názvu indonéský ostrov — tím jejich příbuznost končí.



Návrhy na doplnění pište sem.
Toto téma je uzamčeno. Odpověď nelze zaslat.

0