Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Javascript a oblast působnosti proměnných - díl první

V sérii článků Petra Staníčka se podíváme na jednu z oblastí JavaScriptu, která většině programátorů může připadat samozřejmá a nepřekvapivá, totiž na oblast působnosti proměnných. V prvním článku budou na pořadu dne obyčejné proměnné a funkce. Myslíte si, že máte v problematice jejich působnosti zcela jasno?

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Poznámka redakce: Petr Staníček původně napsal jeden velmi dlouhý článek, který by byl na jedno „učtení“ příliš náročný. Proto jsme po vzájemné dohodě sáhli k jeho rozdělení. První část se věnuje věcem, které by měly být programátorům v JS důvěrně známé – totiž obory platností proměnných a funkcí. V druhém díle bude následovat popis objektů, tříd, metod a možností zapouzdření, ve třetím díle pak uzávěry (closures). První díl je tedy jakousi „předehrou“, a proto může připadat zkušenějším jako opakování známých věcí. 

Napsat něco o oblasti působnosti proměnných v Javascriptu jsem se rozhodl hlavně proto, že jsem nedávno v jedné z velmi temných chodbiček této problematiky zabředl až po krk – a nikoli poprvé – a potřebuji si v tom konečně sám udělat jednou provždy trochu jasno. Přesně podle hesla: „Jestli v něčem nemáš jasno, napiš o tom článek. Jestliže to opravdu nechápeš, napiš o tom knihu. A pokud pořád ještě tápeš, začni to učit.“ Ona ta platnost proměnných v Javascriptu je známý problém zavalený spoustou dezinformací, mylných představ i fám a prakticky každý javascriptový programátor na to dříve či později narazil. A tvrdí-li někdo, že s tím nikdy problém neměl, má ho nejspíš dodnes.

Globální a lokální proměnné

Rozlišování mezi lokální a globální platností proměnných patří mezi základní programátorské dovednosti; míra a způsob jejich odlišení zase mezi základní parametry každého programovacího jazyka. Většina jazyků má v tomto ohledu velmi striktní pravidla, u Javascriptu se to může zdát malinko divočejší, ale pravidla jsou tu také. Ovšem v některých případech poněkud méně průhledná.

Obecně lze říci, že každá proměnná má platnost pro tu úroveň kódu, v níž byla deklarována – aneb jak se říká, byla „uvařena“ (kvůli klíčovému slovu var, které se k deklaraci proměnných používá). Pokud je proměnná deklarována na nejvyšší úrovni, tedy přímo v dokumentu, mimo tělo nějaké funkce, stává se tímto okamžikem proměnnou globální a je dostupná z kteréhokoli místa kódu.

var x = 1;function test() {
   x++;
   alert(x);
   }
x = 2;
test();

Globální proměnné x je deklarací přiřazena hodnota 1. Následně na nejvyšší úrovni kódu je jí přizena hodnota 2. Poté je zavolána funkce test(), která její hodnotu zvýší o jedna a vypíše její aktuální hodnotu, tedy 3.

Lokální proměnné

Pokud je proměnná deklarována uvnitř nějaké funkce, její platnost se zužuje pouze na kód uvnitř této funkce. Navíc je zde jeden zásadní rozdíl: tato proměnná nevzniká hned, ale až při volání své „mateřské“ funkce. A voláme-li ji vícekrát, vzniká pokaždé znova.

function test() {
   var x = 1;
   alert(x);
   x++;
   }
test();
test();

Při načítání skriptu vznikne funkce test, ovšem nic z toho, co definuje její kód – tedy ani proměnná x  – ještě neexistuje. Teprve při volání test() vznikne (lokální) proměnná x, dostane hodnotu 1, ta se vypíše, její hodnota se zvýší o 1 a funkce skončí. Tím tato proměnná x zaniká. Dalším voláním test() se vytvoří nový „klon“ proměnné x a stane se totéž – tj. vypíše se 1, hodnota x se zvýší o jedna, načež zanikne.

Lokální proměnná se uvnitř své „mateřské“ funkce chová jako globální, je tedy dostupná celé této úrovni kódu, tedy i všem funkcím deklarovaným uvnitř uzavírající funkce.

function test() {
   function plus() {
      x++;
      }
   var x = 1;
   plus();
   alert(x);
   }
test();

Zavolá se funkce test(), ta deklaruje svou lokální funkci plus, poté deklaruje svou lokální proměnnou x s hodnotou 1, zavolá funkci plus pro kterou je x proměnnou globální, zvýší tedy její hodnotu o jedna a výsledná hodnota 2 se vypíše.

Je důležité vědět, že mezi globálními a lokálními proměnými stejného jména není vůbec žádná vazba a mohou tedy existovat dvě různé proměnné se stejným jménem, ale odlišným oborem působnosti.

function test() {
   var x = 1;
   alert(x);
   }
var x = 10;
test();
alert(x);

Zde se nejprve deklaruje funkce test, poté globální proměnná x s hodnotou 10. Poté se volá funkce test(), která si vytvoří svou lokální proměnnou x s hodnotou 1, a tu zobrazí. Načež se zobrazí hodnota jiné, tentokrát globální proměnné x, tedy 10.

Vše je lepší uvařené

Jedním z největších zel Javasciptu je skutečnost, že explicitní deklarování proměnných není povinné. Nicméně jeho nepoužívání může vést k řadě problémů a skrytých chyb a je dobrým zvykem slušného programátora vařit úplně každou proměnnou – především právě proto, aby měl zcela jasno v mezích její platnosti.

Pokud se tak z jakéhokoli důvodu nestane, je aspoň důležité vědět, že neznámé (nedeklarované) proměnné se při prvním použití automaticky deklarují na globální úrovni.

function test() {
   x = 10;
   alert(x);
   }
test();
x++;
alert(x);

Zde se volá funkce test(), která přiřazuje hodnotu 10 dosud nikde nedeklarované proměnné x, proto se automaticky vytvoří globální proměnná x a zobrazí se její hodnota 10. Poté globální část kódu této (již deklarované!) proměnné zvýší hodnotu o jedna a následně zobrazí hodnotu 11.

Je opravdu důležité si na tuto vlastnost Javascriptu dávat dobrý pozor, nezřídka se stává, že takováto nedeklarovaná proměnná je použita domněle jako lokální – třeba pro index pole nebo řídicí proměnnou cyklu – ale protože je ve skutečnosti proměnnou globální, její hodnotu někdo zvenčí neočekávaně změní a mohou se začít dít jen těžko odhalitelné chyby. Deklarování proměnných by si měl každý dát za pravidlo i v těch nejmenších a nejpitomějších skriptících – a pokud píšeme nějakou knihovnu nebo vůbec jakkoli sdílený kód, který se může ocitnout ve stránce společně s kódy, které nemáme plně pod svou kontrolou, je to zcela bez diskuse a mělo by to být naprosto povinné.

Proměnné a funkce

Dosud jsem mluvil jen o proměnných, nicméně z hlediska Javascriptu se jako proměnná chová i každá funkce a platí pro ně totéž, co bylo řečeno o proměnných výše. Obvyklý zápis funkce je v podstatě zkrácený zápisem deklarace proměnné a přiřazením funkce jako její hodnoty – neboli tento tvar:

function test(a) {
   return a + 1;
   }

je ekvivalentní tomuto zápisu:

var test = function test(a) {
   return a + 1;
   }

A tak stejně jako proměnné, i funkce definované na globální úrovni jsou globální a dostupné v celém kódu, funkce definované v těle jiné funkce jsou lokální, dostupné jen pro její kód a z hlediska vnějšího kódu neexistují.

function test() {
   function plus(x) { return x + 1 }
   alert( plus(1) );
   }
test();
alert( plus(1) );

Zde se zavolala funkce test, která volá svou interní funkci plus, která zvýší předaný parametr o jedničku. Poté se úplně stejně volá funkce plus z globální úrovně, ale tam již taková funkce neexistuje, což vyvolá chybu Javascriptu.

V dalším díle se podíváme na problematiku tříd a metod, vlastnosti objektů a zapouzdření.

Petr Staníček

Autor je návrhář UI/UX, analytik, grafik, javascriptový vývojář a advocatus diaboli ex offo.

Školení Google+ pro firmy

DW - Školení PPC
  • Jak využít Google+ pro firemní komunikaci a marketing.
  • Čím se liší Google+ od Twitteru a Facebooku z pohledu firemního využití.
  • Jak využít Google+ v souladu s pravidly užívání.
  • Založení Google+ Page (Stránky) krok po kroku, včetně praktických tipů.

Detailní informace o školení Google+ »

Přehled názorů

funkce
Dero 7. 8. 2009 01:07
Nový
├ 
Re: funkce
Aleš Roubíček 7. 8. 2009 06:09
Nový
├ 
Re: funkce
Karel Fučík 7. 8. 2009 08:31
Nový
├ 
Re: funkce
Adam Hořčica 7. 8. 2009 10:53
Nový
└ 
Re: funkce
Petr Staníček 7. 8. 2009 13:26
Nový
 
├ 
Re: funkce
Karel Fučík 7. 8. 2009 13:36
Nový
 
│
└ 
Re: funkce
Petr Staníček 7. 8. 2009 22:00
Nový
 
│
 
└ 
Re: funkce
Karel Fučík 7. 8. 2009 22:27
Nový
 
│
 
 
└ 
Re: funkce
Petr Staníček 7. 8. 2009 22:42
Nový
 
├ 
Re: funkce
Dero 7. 8. 2009 15:50
Nový
 
└ 
Re: funkce
Dero 7. 8. 2009 15:51
Nový
Re: Javascript a oblast působnosti proměnných - díl první
blizz.boz 7. 8. 2009 01:48
Nový
└ 
Re: Javascript a oblast působnosti proměnných - díl první
Aleš Roubíček 7. 8. 2009 06:12
Nový
 
└ 
Re: Javascript a oblast působnosti proměnných - díl první
blizz.boz 7. 8. 2009 12:03
Nový
 
 
└ 
Re: Javascript a oblast působnosti proměnných - díl první
Aichi 8. 8. 2009 10:28
Nový
 
 
 
└ 
Re: Javascript a oblast působnosti proměnných - díl první
blizz.boz 8. 8. 2009 10:47
Nový
 
 
 
 
└ 
Re: Javascript a oblast působnosti proměnných - díl první
Aichi 8. 8. 2009 23:08
Nový
Re: Javascript a oblast působnosti proměnných - díl první
mykhal 7. 8. 2009 01:50
Nový
└ 
Re: Javascript a oblast působnosti proměnných - díl první
Petr Staníček 8. 8. 2009 12:19
Nový
Poslední příklad: zvyšuje o jedničku?
Vít Šesták 7. 8. 2009 07:22
Nový
└ 
Re: Poslední příklad: zvyšuje o jedničku?
Petr Staníček 7. 8. 2009 13:58
Nový
 
├ 
Re: Poslední příklad: zvyšuje o jedničku?
Petr Staníček 7. 8. 2009 14:29
Nový
 
└ 
Re: Poslední příklad: zvyšuje o jedničku?
Vít Šesták 7. 8. 2009 16:06
Nový
 
 
└ 
Re: Poslední příklad: zvyšuje o jedničku?
Petr Staníček 7. 8. 2009 17:13
Nový
Zacyklení při rekurzi
Vít Šesták 7. 8. 2009 07:27
Nový
Re: Javascript a oblast působnosti proměnných - díl první
Michal Augustýn 7. 8. 2009 09:07
Nový
└ 
Re: Javascript a oblast působnosti proměnných - díl první
Daniel Steigerwald 7. 8. 2009 13:30
Nový
 
├ 
Re: Javascript a oblast působnosti proměnných - díl první
Petr Staníček 7. 8. 2009 14:12
Nový
 
│
└ 
Re: Javascript a oblast působnosti proměnných - díl první
Daniel Steigerwald 7. 8. 2009 20:16
Nový
 
└ 
Re: Javascript a oblast působnosti proměnných - díl první
KLoK 7. 8. 2009 23:18
Nový
Uvaření globálních a IE
Leoš Ondra 7. 8. 2009 10:24
Nový
Hack s anonymkou
Vít Šesták 7. 8. 2009 10:59
Nový
└ 
Re: Hack s anonymkou
Daniel Steigerwald 7. 8. 2009 13:31
Nový
 
└ 
Re: Hack s anonymkou
Vít Šesták 7. 8. 2009 16:01
Nový
 
 
└ 
Re: Hack s anonymkou
Daniel Steigerwald 7. 8. 2009 20:53
Nový
 
 
 
└ 
Re: Hack s anonymkou
Vít Šesták 7. 8. 2009 21:02
Nový
 
 
 
 
├ 
Re: Hack s anonymkou
Martin Malý 7. 8. 2009 21:05
Nový
 
 
 
 
└ 
Re: Hack s anonymkou
Daniel Steigerwald 8. 8. 2009 00:11
Nový
 
 
 
 
 
└ 
Re: Hack s anonymkou
Vít Šesták 8. 8. 2009 08:40
Nový
JavaScript díl 1 - proměnné
Daniel Steigerwald 7. 8. 2009 20:45
Nový
├ 
Re: JavaScript díl 1 - proměnné
Martin Malý 7. 8. 2009 20:49
Nový
└ 
Re: JavaScript díl 1 - proměnné
Timy _ 8. 8. 2009 11:21
Nový
 
└ 
Re: JavaScript díl 1 - proměnné
Borek Bernard 8. 8. 2009 12:23
Nový
 
 
├ 
Re: JavaScript díl 1 - proměnné
Daniel Steigerwald 8. 8. 2009 12:49
Nový
 
 
└ 
Re: JavaScript díl 1 - proměnné
povinná 11. 8. 2009 21:55
Nový
Re: Javascript a oblast působnosti proměnných - díl první
PetrP 4. 9. 2009 17:09
Nový
předání proměnné
Johny_S 9. 1. 2010 11:34
Nový
└ 
Re: předání proměnné
Vít Šesták 9. 1. 2010 12:19
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem