JZD – Javascriptové ZD

Pár drobností i větších drobností, které je dobré vědět, když javascriptujete:-)

ZD?

Záhadné ZD? Lze přeložit různě – třeba „základní dovednosti”, „zajímavé detaily” nebo „zákeřné drobnosti“? Vycházím ze svých zkušeností javascriptového samouka a příznávám, že je několik věcí, které alepsoň dle mé zkušenosti mohou začátečníkovi znestadnit (nejen) začátky nebo ho svést z cesty vývoje dlouhodobě udržovatelného rozsáhlejšího kódu.

  • začátečník netuší, že je JS objektový a navíc bohužel nemá tak striktní pravidla ani terminologii jako C++, Java apod.
  • existuje mnono návodů, které lze použít jako black box a ony fungují, dokud jich nesmícháte moc dohromady;-)
  • je několik možností jak dělat totéž různým způsobem (a nejsou IMHO mezi JS vývojári příliš zažité konvence jak psát kód; trošku pomáhá použití JS knihoven)
  • obvykle nemáte IDE, které by vám pomáhalo:-)

Pozn.: některé příklady vyžadují mít zapnutou Firebug konzoli.

Globální proměnné jsou zlo

Globální proměnné jsou ty, které:

  • nejsou deklarovány pomocí var
  • jsou deklarovány pomocí var, ale nejsou zanořeny v žádném objektu

Globální proměnné jsou pak vlastnostmi „kořenového” objektu window. Zkuste si třeba ve Firebugu zadat do konzole „window” a uvidíte kolik jich tam máte (pozor jsou tam skutečně všechny tj. např. i ty od různých pluginů).

Určitě se bez nich zcela neobejde, ale vyplatí se je jejich počet eliminovat. Jak?

  • proměnné, které jsou využívány jen lokálně, tj. např. v rámci nějaké funkce deklarovat v rámci funkce
    (případně použít anonymní funkce)
  • funkce které spolu souvisí seskupit do jednoho objektu (chcete-li jmenného prostoru nebo Class)

Proč?

  • prevence kolize názvů (vaše názvy mohou kolidovat s kódem, který jste nepsali ani vy sami – pluginy, měřící kódy, některé pluginy prohližeče)
  • přehlednější (čitelnější, více samodokumentační) kód (zapouzdřování do objektů)

Chcete příklad? Jak snadno se dostanete do kolize – a jak snadno ji vyřešíte anonymní funkcí.

Chcete další důvody a příklady? Máte je mít.

Jednoduchá deklarace objektů bez new

Pole

  • var myArray = []
  • Objekt (literál)
  • var myObject = {}

Dvě nebo tři = ?

Obvykle používáme v JS pro porovnání dvou hodnot operátor ==. Pokud obě hodnoty nejsou stejného typu, je automaticky provedena konverze jedné hodnoty, abychom neporovávali „hruškys jablkama”.

Někdy si ani porovnání s konverzí nemusíme uvědomit. Například
var hodnota = „“; if(hodnota) {};
by se také dal popisněji zapsat jako
var hodnota = „“; if(Boolean(hodnota) === true ) {};

Pokud nechcete, aby se při porovnání prováděla konverze typů (typecasting), použijte ===.

Více o datových typech v JS.

Nepovinné parametry funkcí a jejich implicitní (defaultní) hodnoty

var functionTest = function(optionalParam) {
optionalParam = (typeof optionalParam == 'undefined') ?
'default value' : optionalParam;
return optionalParam;
};

Kod je asi čitelný. Je možná poznámka: ternární operátor (logická podmínka) ? pravda : nepravda, v našem příkladu zařídí, že pokud není optionalParam definován, nastaví se jeho hodnota na ‚default value‘. Ve většině případů, lze zapsat dokonce ještě stručněji optionalParam = optionalParam || ‚default value‘.

Pokud má funkce mnoho parametrů (argumentů), vyplatí se nepředávat jednotlivé parametry, ale jeden objekt obsahující hodnoty jednotlivých argumentů. Pro další studium:-) doporučuji článek JavaScript Function Arguments: Default Values, Passing Objects, and Overloading

Asociativní pole (vs. JSON vs. Object)

Asociativní pole (chcete-li Map) v JS sice jako datová struktura neexistují. Tento nedostatek lze snadno použít zneužitím obecného Objectu. Asociativním polem je de facto JSON notace.

Existují 4 způsoby jak zapsat to samé (demo příklad). Ve všech případech je „pole” pouhým objekterm (tj. instanceof Array vrátí false). Z toho plyne, že nemůžeme používat žádné metody pro prácí s Array ( join(), push() apod.).

// Pseudo associative array
alert("Example 1");
var myObj1 = {};
myObj1["cz"] = "Czech";
myObj1["en"] = "English";
myObj1["de"] = "German";
for (var key in myObj1) {
alert(key + " is the abbreviation for " + myObj1[key]);
}
// Object dot notation
alert("Example 2");
var myObj2 = {};
myObj2.cz = "Czech";
myObj2.en = "English";
myObj2.de = "German";
for (var key in myObj2) {
alert(key + " is the abbreviation for " + myObj2[key]);
}
// Object literal
var myObj3 = {
cz: "Czech",
en: "English",
de: "German"
}
alert("Example 3");
for (var key in myObj3) {
alert(key + " is the abbreviation for " + myObj3[key]);
}
// JSON
var myObj4 = {
"cz": "Czech",
"en": "English",
"de": "German"
};
alert("Example 4");
for (var key in myObj4) {
alert(key + " is the abbreviation for " + myObj4[key]);
}

Array vs. Object (a iterace)

Jak jsme viděli výše asociativní pole není polem. Zato každé Array je zároveň Object. Co z toho plyne?

Napadlo vás někdy iterovat polem jako objektem? Jde to, ale moc dobrý nápad to není. Iterovat totiž budete nejen prvky pole, ale všemi metodami Array. Problém nastane až v okamžiku, kdy Array rozšíříme o naší vlastní metodu (např. max() – která má vrátí největší číslo z pole). Protože iterujeme všemi vlastnostmi objektu najednou nám se nám kromě prvků pole objeví i metoda max().

Pokud chcete zobrazit jen prvky, musíte metody přídané pomocí prototype přeskočit testováním na typeof myObj[key] != „function“ (demo příklad).

Dejte vědět….

Máte lepší postup? Našli jste chybu? Nesouhlasíte?

Máte něco, co vás potrápilo a chcete se podělit? Dejte vědět v diskuzi!