JavaScript je ZLO 2.0
Argumenty funkcí - stálý zdroj zábavy
Co se týče funkcí v JavaScriptu, žádný argument není povinný. To je sice lepší než kdyby byly povinné všechny, nicméně zas až taková výhra to taky není.
Jestli o argumentech funkcí víte všechno tak už ani dál nečtěte protože tohle bude jen a jen o nich.
Nejdříve něco základních znalostí:
Vlastnosti length a arity: máme-li funkci definovanou předpisem var fn = function (a, b, c) { ... };, počet očekávaných argumentů můžeme kdykoli zjistit z atributu length ( fn.length == 3 ) nebo z atributu arity (fn.arity == 3).
Objekt arguments: zavoláme-li funkci, všechny předané argumenty se uloží do objektu arguments které je lokálně dostupné uvnitř této funkce. Zavoláme-li např. funkci f(10, 20), bude arguments[0] == 10 a arguments[1] == 20. Vlastnost arguments.length obsahuje skutečný počet předaných argumentů.
Jak správně podotkl Oswald, objekt arguments se sice tváří jako číslované pole ale není tak docela pole (tzn. arguments != instanceof Array).
Jestliže funkci f(a, b, c) { ... } zavoláme f(10, 20), bude f.arity == 3 a uvnitř prováděné funkce bude arguments.length == 2. Můžeme tak snadno zjistit zda byly zadány všechny předepsané argumenty. V tomto případě nebyly a proto typeof c == "undefined".
Jak vidno, žádný argument není tak docela povinný a naopak, funkci můžeme zavolat i s větším počtem argumentů než má předepsáno. “Nadbytečné” argumenty jsou dostupné pouze z objektu arguments.
Reference arguments.calee: toto je reference na funkci která právě probíhá, tedy na tu které patří pole arguments. Této reference lze využít k rozličným fintám, například pokud chceme aby funkce proběhla právě jednou, můžeme napsat
if (arguments.calee.done) {
return false; // function already run - exit
} else {
arguments.calee.done = true; // function runs first time - continue
}
…
};
Ošetření argumentů funkce
Argumenty které nejsou povinné by měly mít vhodné “default” hodnoty. Pro přehlednost by měly být uvedeny hned na začátku funkce:
if (typeof myNum == "undefined") {
myNum = null;
}
if (typeof myBool == "undefined") {
myBool = true;
}
…
};
U argumentů, kde nemůže dojít k omylu způsobenému typovou konverzí, můžem použít zkrácenou formu
myObj = myObj || null;
…
};
která je ještě relativně dobře čitelná, ale raději ji používejte jen když opravdu dobře víte co děláte a jen v takto jednoduchých případech.
Argumenty které jsou povinné doporučuji ponechat neošetřené - jednak se tím šetří kód (přenos po síti bývá často stále ještě dost pomalý), je to kompatibilní se staršími Internet Explorery a pokud argument nepřijde, program obvykle rychle havaruje a tedy se chyba snadněji hledá.
Pokud budete chtít být opravdu poctiví, doporučuji vyhodit okamžitě výjimku, což však není kompatibilní se staršími MSIE.
if (typeof myArg == "undefined") {
throw "Crap! Exception in function myNs.myFn - argument myArg is missing";
}
…
};
Konvence pro řazení argumentů
Základní řazení argumentů při deklaraci funkce je určené omezeními JavaScriptu - nejdříve jsou vždy povinné argumenty a za nimi teprve nepovinné. U nepovinných argumentů je to složitější, nicméně je vždy dobré řídit se zdravým rozumem a dávat dopředu argumenty které budou uživatelé funkce častěji nastavovat.
KISS
Závěrem bych ještě dodal jednoduchou poučku která platí nejen pro funkce a jejich argumenty:
“Keep it simple stupid” neboli “udělej to jednoduše jako pro blbečky”. Prostě si představte toho nejhloupějšího programátora na světě jak luští vaši funkci a snaží se zjistit co vlastně dělá a pak to napište tak aby to pochopilo i malé dítě (a tedy i já).
Tento článek byl přidán 13.04 2007
5 Komentářů k článku “Argumenty funkcí - stálý zdroj zábavy”
Jenom drobné upřesnění: arguments není pole (teoreticky se jedná o instanci třídy Arguments). Sice např. Opera skutečně předává array, ale Firefox i IE vrací na test “arguments instanceof Array” false a minimálně ve Firefoxu nejsou u objektu arguments k dispozici metody jako push apod.
Je to tak, informaci jsem upravil. Abych řekl pravdu, “rádoby objektová” část JavaScriptu mě velice irituje. Kdyby autoři neblbli a ponechali ho jako “jazyk založený na seznamech” kterým původně byl, mohl být JavaScript mnohem přehlednější a nedocházelo by k takovým šílenostem co ukazuje Douglas Crockford.
V části “Ošetření argumentů funkce” se mají předávat argumenty myNum a myBool, ale ty tam posléze kontroluješ argument myInt a né myNum (i když bych řekl, žes chtěl raději napsat místo myNum myInt )
Máš recht, opraveno. Ale raději jsem napsal myNum, myslím že je to vhodnější.
no zadna slava mely by ste to zlepsit