|
|
Jak jistě víte v Javascriptu je dán rozsah působnosti funkční působností. Proměnné jsou vytvářeny ve funkcích. Mimo funkce nejsou proměnné viditelné. Ale proměnná definovaná v bloku kódu je viditelná i mimo něj.
var a = 1; function f(){var b = 1; return a;}
f();
Výsledek bude 1, tedy proměnná a je definovaná v bloku, tedy mimo funkci je viditelná a také je viditelná ve funkci.
Jestliže ovšem zavoláme proměnnou b, která je definována uvnitř funkce f():
b;
tak se k jeho hodnotě nedostaneme, čili výsledek v tomto případě nebude žádný.
Jestliže definujete například novou funkci n() uvnitř funkce f(), funkce n() bude mít nejen přístup ke svým proměnným, ale také k proměnným funkce f(), tedy k rodičovským proměnným svého rodiče funkce f():
var a = 1;
function f(){
var b = 1;
function n() {
var c = 3;
}}
Funkce vytváří své pole působnosti když jsou vytvářeny, ne pokud jsou volány. Například:
function a(){var c = 1; b();}
function b(){return c;}
a();
Uvnitř funkce a() voláme funkci b(). Lokální proměnná je definována ve funkci a(), dalo by se očekávat, že funkce b() bude mít přístup k proměnné c, ale ne v tomto případě. V době, kdy byla funkce b() definována neexistovala žádná proměnná c, na kterou by mohla funkce b() vidět.
b(), stejně tak a() mají přístup ke svému poli působnosti, a také k datům jež jsou v globálním prostředí. Funkce a() nemá přístup k lokálním proměnným funkce b() a naopak.
Když je definována funkce, „pamatuje“ si své pole působnosti, které jí přisoudíte. To neznamená, že si funkce pamatuje každou proměnnou nacházející se v jejím poli působnosti. Do funkce můžete přidávat proměnné, mazat je uvnitř působnosti funkce, a funkce budou pracovat podle nejnovějšího stavu.
Budeme-li chtít aby funkce b() viděla na proměnnou c, tak ji musíme deklarovat mimo těl funkcí v globálním prostoru funkcí, viz příklad:
var c=1
function a(){c, b();}
function b(){return c;}
Pojďme se podívat na uzávěry na jednotlivých ilustracích. Existuje globální pole působnosti. Můžete si ho představit jako vesmír, který vše obsahuje:
Funkce mají vlastní soukromý prostor a můžete ho použít pro ukládání dalších proměnných(a funkcí):
Pokud se na obrázku nacházíme v bodu a jsme v globálním prostoru. Pokud jste v bodu b, nacházíte se uvnitř prostoru funkce F, pak máte přístup ke globálním prostoru a prostoru funkce F. Pokud jste v bodě C, který je uvnitř funkce N, pak můžete přistupovat ke globálním prostoru, prostoru funkcí F a N. Nemůžete číst proměnnou b z umístnění proměnné a, protože proměnná b je neviditelná mimo funkci F. Pokud byste chtěli, mohli byste číst proměnnou b z místa proměnné c.
Zajímavá věc - uzávěry – nám umožňují vyskočit funkcí N přímo do globálního prostoru:
Příklad 1. uzávěry:
function f(){
var b = “b”;
return function(){
return b;
}
}
Proměnná b je umístněna v prostoru funkce f() a tudíž z globálního prostoru nedostupná. Podívejte se na návratové hodnoty funkce f(), jsou to návratové hodnoty jiné funkce. Můžete si ji představit jako funkci N zobrazenou ve výše uvedené ilustraci. Tato nová funkce má přístup ke svému soukromému prostoru, k prostoru funkce f() a ke globálnímu prostoru. Tedy vidí i na proměnnou b. Protože funkce f() je volatelná z globálního prostoru, jedná se vlastně o to, že funkce f je globální funkcí. Nová globální funkce bude mít tedy přístup k soukromému prostoru funkce, viz příklad:
var n = f();
n();
výsledek bude písmeno b.
Příklad 2. uzávěry:
Výsledek tohoto příkladu bude stejný jako předchozího příkladu, ale způsob, jak toho dosáhneme, je trochu jiný. Funkce f() nevrací funkci, ale vytvoří novou globální funkci n() uvnitř svého těla.
Před definováním naší funkce f() vytvoříme novou globální proměnnou n.
var n;
function f(){
var b = “b”;
n = function(){
return b;
}
}
Co se stane, když vyvoláte funkci f()?
f();
Nová funkce je definovaná uvnitř funkce f(), a protože uvnitř funkce není u proměnné n označení var, stává se globální. Během volání má přístup k prostoru funkce f() i funkce n().
V tomto případě budete muset ovšem před voláním funkce n() zavolat funkci f() :
f();
n();
Podívejme se na následující for cyklus. Nová funkce bude přidána do pole a bude navracet jeho konečnou hodnotu:
function f() {
var a = [];
var i;
for(i = 0; i < 3; i++) {
a[i] = function(){
return i;
} ;
}
return a;
}
var x=f();
x[0]();
x[1]();
x[2]();
Všechny výsledky se budou rovnat třem
Výsledek není takový, jaký jsme očekávali. Proč je výsledkem této funkce stále číslo 3? Vytvořili jsme v cyklu for defakto tři uzávěry poukazující stále na stejnou proměnnou. Uzávěry si nepamatují hodnoty, ukazují pouze odkazem, neboli referencí na proměnnou i. Po provedení for cyklu je hodnota rovna třem. Takže všechny tři funkce budou mít stejnou výslednou hodnotu.
Jak tedy vytvořit takový for cyklus, aby fungoval tak jak bychom očekávali? Budete potřebovat tři proměnné.
Elegantním řešením je použití jiné uzávěry:
function f() {
var a = [];
var i;
for(i = 0; i < 3; i++) {
a[i] = (function(x){
return function(){
return x;
}
})(i);
}
return a;
}
Nyní získáme správné hodnoty: var a = f(); a[0](); výsledkem bude číslo 0
Pokud jste ještě u mého textu neusnuli a došli až sem, tak Vám děkuji za přečtení tohoto článku. Doufám, že se těšíte na další články ze světa “kouzelného” javascriptu ![]()
O programování a všem okolo využívá WordPress MU a běží na Blog.zive.cz. Vytvořte si svůj vlastní blog
Sledování přes RSS: články
a komentáře
Partnerská sekce pro IT profesionály:
Microsoft TechNet/MSDN