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

Hlavní navigace

Názory k článku
Javascript a oblast působnosti proměnných - díl třetí

Aichi
Aichi (neregistrovaný) ---.seznam.cz
17. 8. 2009 10:18 Nový

Re: Javascript a oblast působnosti proměnných - díl třetí

celé vlákno

Pokud píšu o uzávěrech (já vím, psal jste, že tomu nerozumíte, proto o tom píšete), tak je velice jednoduché skončit u that = this. Pak se ale nedivme, že lidi co k tomu příjdou se ptaj, proč je někde this a někde that.

Mnohem lepší by bylo zmínit možnost zakonzervovat si this pomocí konstrukce apply.

fos4
fos4 (neregistrovaný) ---.customer.poda.cz
17. 8. 2009 10:24 Nový

Re: Javascript a oblast působnosti proměnných - díl třetí

celé vlákno

Byl jste rychlejsi, zrovna jsem chtel napsat :

var XYZ = {};
XYZ.test = function(param) {
   this.X = param;
   var init = function() {
      if (this.X==undefined) alert('chyba');
      else alert('je to ok ');
   }
   init.call(this); // init.apply(this);
};
XYZ.test(1);
_
_ (neregistrovaný) 208.43.126.---
23. 8. 2009 19:14 Nový

Re: Javascript a oblast působnosti proměnných - díl třetí

celé vlákno

Mnohem lepší by bylo zmínit možnost zakonzervovat si this pomocí konstrukce apply.
Čo myslíte pod tým zakonzervovaním?
Bez toho, aby bolo to pôvodné this do niečoho uložené to nepôjde.

pracj3am
pracj3am (neregistrovaný) ---.lundegaard.cz
17. 8. 2009 12:22 Nový

Jestli tomu dobře rozumím

celé vlákno

tak bez anonymní funkce to bude také fungovat

var XYZ = {};
XYZ.test = function(param) {
   this.X = param;
   function init() {
      if (this.X==undefined) alert('chyba');
      else alert('je to ok ');
   }
   init();
};
XYZ.test(1);
Aichi
Aichi (neregistrovaný) ---.seznam.cz
17. 8. 2009 13:43 Nový

Re: Jestli tomu dobře rozumím

celé vlákno

A spustil jste si to?

pracj3am
pracj3am (neregistrovaný) ---.lundegaard.cz
17. 8. 2009 15:33 Nový

Re: Jestli tomu dobře rozumím

celé vlákno

Zkusil a zjistil, že je jedno jestli je funkce anonymní nebo ne.

Mám tam ale jedno mlhavé místo, kód níže vrací:

chyba
chyba
je to ok
je to ok

A tomu druhému řádku příliš nerozumím. (Možná v seriálu chybí lepší vysvětlení operátoru new.)

var XYZ = {};
XYZ.test = function(param) {
   this.X = param;
   var init = function() {
      if (this.X==undefined) alert('chyba');
      else alert('je to ok ');
   }
   init();
};
var test = XYZ.test;

XYZ.test(1);
A = new XYZ.test(1);
test(1);
B = new test(1);
Aichi
Aichi (neregistrovaný) ---.seznam.cz
17. 8. 2009 16:04 Nový

Re: Jestli tomu dobře rozumím

celé vlákno

Opravdu zkusil? a opravdu ten vas priklad dava stejnou hodnotu jako ten nahore? Ne nedava! takze to jedno neni. Jake mlhave misto make krom toho new? Jaky druhy radek?

Nicmene pro vasi informaci, ty vase 4 posledni radky: – Prvni je stejny jako vyse a dokazuje, ze nemate pravdu. – Druhym volate funkci test jako konstruktor a tedy v A je objekt s jedinou vlastnosti a to X, funkce init se k nemu nevztahuje a tudiz nezna this jako tento objekt – Treti je volani pouze funkce test, pak this = globalni objekt (window) a cirou nahodou je this v init take globalni objekt, pak to vypise OK – Ctvrty je to same jako Druhe, nicmene vam predchozi volani nadefinovalo window.X, tudiz to projde, kdyby byl zakomentovan treti radek, neprojde to taky

Co presne nechapete na operatoru new?

pracj3am
pracj3am (neregistrovaný) ---.lundegaard.cz
17. 8. 2009 16:26 Nový

Re: Jestli tomu dobře rozumím

celé vlákno

Opravdu jsem si to zkusil, anonymni nebo neanonymni funkce – vysledek stejny:

var XYZ = {};
XYZ.test = function(param) {
   this.X = param;
   var init = function() {
      if (this.X==undefined) alert('chyba');
      else alert('je to ok ');
   }
   function initb() {
      if (this.X==undefined) alert('chyba');
      else alert('je to ok ');
   }
   init();
   initb();
};

Jsem zmaten kvůli tomu, že autor psal, že lokálně definované funkce uvnitř konstruktoru slouží jako privátní metody a že jsou v nich přístupné všechny lokální i veřejné proměnné. Což tedy, jak se ukazuje, není pravda.

Aichi
Aichi (neregistrovaný) ---.seznam.cz
17. 8. 2009 17:09 Nový

Re: Jestli tomu dobře rozumím

celé vlákno

Problém vašeho zmatení je nejspíš v tom, te v tomto případu žádný konstruktor není.

Adam Hořčica
17. 8. 2009 17:19 Nový

Re: Jestli tomu dobře rozumím

celé vlákno

this nemůžete brát jako „normální“ proměnnou. V lokálně definované funkci jsou přístupné lokální proměnné díky uzávěře (closure). this se ale uzávěra netýká, o tom je právě druhá část tohoto článku (část Tohle & Tamto).

cHLeB@
cHLeB@ (neregistrovaný) ---.seznam.cz
17. 8. 2009 13:44 Nový

apply / call

celé vlákno

A zrovna o tedle moznosti (apply / call) se pise v clanku na ktery pixi odkazuje pod svym clankem .. :) … docela sranda :)

Jakub Vrána aura:43
17. 8. 2009 16:18 Nový

Velikost písmen

celé vlákno

Zmatek s velikostí písmen bohužel pokračuje. Jeho důsledkem je teď to, že se článek odkazuje na neexistující objekt Window (ve skutečnosti je to objekt  window).

Vít Šesták aura:72
23. 8. 2009 13:52 Nový

Re: Velikost písmen

celé vlákno

Budu chytat za slovo. Zkusil jsem do asresního řádku prohlížeče (FF řady 3.5) napsat obojí: javascript:aler­t(Window) javascript:aler­t(window)

Hele, oboje háže „[object Window]“.

No dobře, oboje je něco jinýho. javascript:aler­t(Window.docu­ment) vs. javascript:aler­t(window.docu­ment) to koneckonců dokazuje. Window je AFAIK „třída“ (prototyp) pro window.

Toto ukazuje, jak je důležité na takovou konvenci dbát!

Daniel Steigerwald aura:51
23. 8. 2009 20:15 Nový

Co je to Window

celé vlákno

Upřesním. Když se v kódu objeví ‚Window‘, je jasné, že autor neví která bije. Internet Explorer (6/7) totiž na rozdíl od ostatních prohlížečů neodkazuje na konstrukční funkci (constructor), ale na historické dědictví, známé jako [Interface prototype object]. Internet Explorer podporuje plnohodnotný prototype/con­structor pouze pro objekty: Array, Boolean, Date, Error, Function, Number, Object, RegExp a String. [Interface prototype object] je něco jako polo-prototype, instancím lze přidat vlastnosti, avšak instance samotné constructor nemají. Navíc je tento interface podporován pouze pro několik BOM typů: window, option, image (myslím, že to jsou všechny) Žádný smysluplný kód nikdy nikde ‚Window‘ nepoužívá, snad krom nějakých prehistorických copy&past mousehover příkladů.

Jakub Vrána aura:43
23. 8. 2009 21:32 Nový

Re: Velikost písmen

celé vlákno

Ano, důležitost konvence se ukáže třeba v případě, kdy alert(Window) zkusíš v IE nebo když v kterémkoliv prohlížeči napíšeš třeba alert(new regexp). Firefox v alertu píše název konstrukční funkce, ze které je objekt odvozen, např. u document to je HTMLDocument.

Petr Staníček aura:83
26. 8. 2009 11:14 Nový

Re: Velikost písmen

celé vlákno

Objekt Window namísto window byl překlep. Tu větu jsem do článku dopisoval dodatečně a narychlo až při finální korektuře (redakce může potvrdit) a prostě mi to uteklo. Samozřejmě, moje chyba a omlouvám se. Nicméně rozdíl mezi nimi je mi znám a nikoho úmyslně nematu. Děkuji za pochopení.

Poprosím redakci o opravu, ať to nemate aspoň pozdější čtenáře.

radik
radik (neregistrovaný) ---.logos.cz
18. 8. 2009 11:07 Nový

Tisk

celé vlákno

Nevim jak ostatnim, ale ja kdyz si chtel vytisknout clanek z Firefoxu, tak zmizely vsechny zdrojaky, zustaly z nich jen cisla radek ;)

radik
radik (neregistrovaný) ---.logos.cz
18. 8. 2009 11:18 Nový

Re: Tisk

celé vlákno

Tak dela to nejen v FF, ale i v IE, O a Ch.

Martin Malý aura:93
18. 8. 2009 11:21 Nový

Re: Tisk

celé vlákno

Máte pravdu. To není příjemné, předám to vývojovému oddělení k prozkoumání. Do té doby si zkuste před tiskem vypnout JS. Za potíže se omlouváme.

Jakub Vrána aura:43
20. 8. 2009 11:26 Nový

Deklarace proměnné po definici uzávěru

celé vlákno

Uzávěr sice skutečně vidí proměnné deklarované ve funkci až po jeho definici, ale je lepší se tomu vyhnout. Uzávěr se o proměnné totiž dozví až když k její deklaraci interpret skutečně dojde. Do té doby ale může uzávěr někdo zavolat (ať už sama funkce nedopatřením nebo třeba asynchronně při obsluze nějaké události). V tom případě by vznikla při zápisu do proměnné uzávěrem globální proměnná. Lepší je proto deklarovat všechny proměnné vždy na začátku funkce.

Chování lze ověřit na tomto kódu:

function f() {
    var g = function () {
        x = 2;
    }
    g();
    var x = 1;
}
f();
console.log(x);

Další užitečné konvence uvádí Dougles Crockford.

_
_ (neregistrovaný) ---.foebud.org
22. 8. 2009 21:24 Nový

Re: Deklarace proměnné po definici uzávěru

celé vlákno

V vašom kóde vidí interpret x vo funkcii g hneď, no má hodnotu undefined.
Takže ku vytvoreniu globálnej premennej x v žiadnom prípade nepríde.

Vít Šesták aura:72
23. 8. 2009 13:55 Nový

Re: Deklarace proměnné po definici uzávěru

celé vlákno

To je kvalitní nesmysl! Jak ho má vidět?

_
_ (neregistrovaný) ---.hsd1.mi.comcast.net
23. 8. 2009 17:04 Nový

Re: V. Šesták

celé vlákno

Neviem na koho reagujete, použil som terminológiu J. Vrány o „videní“ premennej.
Treba vyskúšať tento kód:

function f() {
  var g = function () {
    alert(x); // undefined
    x = 2;
  }
  alert(x); // undefined
  g();
  alert(x); // 2
  var x = 1;
  alert(x); // 1
}
f();
alert(x);  // vyvolá chybu, globálna premenná x neexistuje
Vít Šesták aura:72
23. 8. 2009 17:37 Nový

Re: V. Šesták

celé vlákno

Omlouvám se, máte pravdu. Koukám, že v tomto se JS chová zvláštně a že mě stále může i zde překvapit. To, co mě dostalo, je možné demonstrovat snadno: 

function f() {
  e = 5;
  var e;
};
f();
alert(window.e); // Pokud ve funkci f vznikla vlastnost globálního objektu e místo lokální proměnné e,
// vypíše pětku.
// Pokud funkce f touto chybou netrpí, vypíše undefined.

Když zakomentuju řádek „var e;“, tak se změní chování. A <b>vůbec nevadí, že proměnnou vařím až po jejím používání!</b>

Viděli jste už někdo někde jinde takovouto zvláštní směs statického a dynamického chování?

_
_ (neregistrovaný) ---.onlinemartin.org
23. 8. 2009 17:55 Nový

Re: V. Šesták

celé vlákno

To vysvetlenie nie je až tak zložité, nasledujúce dve definície funkcie sú ekvivalentné – ak sú miesto toho komentára tie isté príkazy:

function f(){
  var x;
  /*
  príkazy
  */
  x = 1;
}
function f(){
  /*
  príkazy
  */
  var x = 1;
}

Podobne sa chovajú aj funkcie, je ich možné volať už pred ich definovaním, teda pokiaľ sú definované tak, ako vyššie, nie literálom. Kód je spracovávaný na dvakrát a takéto veci sú spracované pri tej prvej analýze.

Vít Šesták aura:72
23. 8. 2009 17:58 Nový

Re: V. Šesták

celé vlákno

Já jsem to pochopil, ale zdá se mi to divné…

Vít Šesták aura:72
23. 8. 2009 19:25 Nový

Re: Deklarace proměnné po definici uzávěru

celé vlákno

Shrnul bych to takto: * při obsluze události to nastat jen tak nemůže, události jsou řazeny do fronty ke zpracování v jednom vlákně. Výjimku by ale mohlo tvořit třeba yield a volání zevnitř funkce není nemožné. * Globální proměnná takto vzniknout nemůže. * Rozhodně je přehlednější „varovat“ proměnné před použitím než až po použití. Už kvůli zvyku programátorů z jiných jazyků. * Pozdější „varování“ proměnných může také vést k jejich inicializaci po určité úpravě.

Ve výsledku bych považoval konvenci „nejdřív ‚varuj‘“ za něco, co skoro nic nestojí, ale může se hodit a je to slušné. Podobně jako odsazování kódu.

Michal Augustýn
22. 8. 2009 20:47 Nový

vznik closure

celé vlákno

Možná by ještě stálo za zmínku, že closure v JavaScriptu vzniká vždy na úrovni funkce. To proto, že v jiných jazycích s funkcionálními rysy (např. C#) může closure vzniknout na úrovni bloku.

_
_ (neregistrovaný) ---.81.77.40.188.clients.your-server.de
22. 8. 2009 22:12 Nový

Zmiznutie lokálnej premennej x vo funkcii zpracuj?

celé vlákno

Tým svojim osvieteným pohľadom len mätiete ostatných.
Tá premenná x po skončení funkcie zpracuj vôbec nezmizne,
ale práve zostane uchovaná v tej funkcii zadanej do toho onclicku.
Toto vysvetlenie je oveľa jednoduchšie, než tie „zálohy kontextu“ so špeciálnym správaním.
Treba vyskúšať tento kód a bude to oveľa jasnejšie, že žiadne zálohy kontextu sa nerobia a pracuje sa vo všetkých funkciách s tou istou premennou x:

var ukazx1, ukazx2, nastavx1, nastavx2;
function f(){
  var x;
  function u1(){alert(x);}
  function u2(){alert(x);}
  function n1(t){x = t;}
  function n2(t){x = t;}
  ukazx1 = u1;
  ukazx2 = u2;
  nastavx1 = n1;
  nastavx2 = n2;
}
f();
nastavx1(1);
ukazx1(); // 1
ukazx2(); // 1
nastavx2(2);
ukazx1(); // 2
ukazx2(); // 2
_
_ (neregistrovaný) ---.digineo.de
22. 8. 2009 22:23 Nový

Re: Zmiznutie lokálnej premennej x vo funkcii zpracuj?

celé vlákno

Pred tým komentárom som to neprečítal celé, takže tá kritika nie je úplne oprávnená,
no to o tých „zálohách kontextu“ platí.

Michal Augustýn
22. 8. 2009 23:02 Nový

Re: Zmiznutie lokálnej premennej x vo funkcii zpracuj?

celé vlákno

IMHO to o „zálohách kontextu“ platí. Ve Vašem příkladě se také jedná o „zálohu kontextu“ – je zde ale pouze jedna, protože funkce f je volána jen jednou – to Vás asi zmátlo.
Prostě proměnná x existuje vždy v nějakém kontextu a pokud někdo ten kontext nějak referencuje, tak ho GC nepožere, takže pořád existuje. V uvedených případech je kontext referencován přes proměnnou x, která je referencovaná vnořenou funkcí (resp. funkcemi), jejíž reference je přiřazena do globální proměnné.

_
_ (neregistrovaný) ---.nullroute.net
22. 8. 2009 23:49 Nový

Re: Zmiznutie lokálnej premennej x vo funkcii zpracuj?

celé vlákno

Kód mi jasný, nič ma nezmiatlo. Ono trochu záleží, čo je pod tým zmiznutím premennej a kontexte myslené. Ako definujete ten kontext? Lepšie by bolo povedať, že na tú premennú existujú viaceré odkazy a netreba potom rozmýšľať o „kontexte“, platnom, keď funkcia skončí, ako v článku. Ten „uzáver“ by nejakým spôsobom mohol fungovať, aj keby funkcia neskončila. Teda uvažovať tak, že je referencia na tú premennú x a nie na nejaký ťažko definovateľný kontext.

t42
t42 (neregistrovaný) 77.48.59.---
23. 8. 2009 16:54 Nový

terminologie

celé vlákno

mozna spis nez „zaloha kontextu“ by slo pouzit „reference na kontext“, alespon takto se closures popisuji v anglicky psane literature a tak mi to prijde presnejsi, protoze „zaloha“ IMHO implikuje spis klon, ktery nema vztah ke svemu originalu, pritom ale o ten vztah jde predevsim (bez nej by nebylo treba delal triky s prirazovanim iteracni promenne do lokalni promenne nebo s prirazovanim this do that, prave proto, aby vznikla closure)

ale jinak velmi kvalitni clanek

Vít Šesták aura:72
23. 8. 2009 17:05 Nový

Re: terminologie

celé vlákno

„reference na kontext“ To je celkem vystihující. Běh funkce má referenci na svůj kontext, kam se ukládají lokální proměnné. Je-li vytvořena lokální funkce, pak samotná lokální funkce dostává referenci na kontext běhu vnější funkce. V případě zavolání této funkce vznikne kontext, který se smíchaný s kontextem přiřazeným k funkci, takže vidím i proměnné z vnějších funkcí. V souvislosti s referencemi bývá zmiňován garbage collector. Zde by fungovalo i počítání referencí, bylo-li by správně napsáno. Ten vysvětluje ty „zálohy“ elegantněji: pokud funkce doběhne, pak běhu této funkce zanikne reference. Pokud tu ale je reference na její kontext, pak prostě nebude uklizen. To mi zní čistěji než „záloha kontextu“. Ve výsledku to ale zvenku vyjde nastejno. Implementačními detaily se zde nezabýváme.

_
_ (neregistrovaný) ---.eicat.ca
23. 8. 2009 17:35 Nový

Re: terminologie

celé vlákno

Celý ten pojem „kontextu“ mi príde nadbytočný.
Čo je chybné na úvahe, že premenná x v prvom kóde článku existuje ďalej aj po skončení funkcie zpracuj?
V tej funkcii predanej do onclick nie je vytváraná žiadna ďalšia premenná, tak sa mi zdá logické a najjednoduchšie uvažovať o tom, že premenná x existuje aj po skončení funkcie zpracuj.

_
_ (neregistrovaný) ---.catbull.com
23. 8. 2009 19:04 Nový

Existencia premennej counter v dobe definovania ovládačov

celé vlákno

V článku je že: … proměnná counter v době definování ovladačů ještě neexistovala … (4. kód)
No v skutočnosti tá premenná vtedy už existovala, len jej hodnota bola vtedy undefined.

Michal Augustýn
24. 8. 2009 21:24 Nový

A co let?

celé vlákno

Pokud se máme bavit o JavaScriptu obecně, pak by v souvislosti s closures stálo za zmínku klíčové slovíčko let, které umožní vytvořit closure uvnitř funkce. Dostupné je od verze 1.7.

_
_ (neregistrovaný) ---.ckt.net
24. 8. 2009 22:03 Nový

Re: A co let?

celé vlákno

To je vec, ktorá by nefungovala vo veľkej časti súčasných prehliadačov so zapnutým funkčným JavaScriptom.
Vytvorenie „uzáverov“ je možné aj iným spôsobom, no je to zlé riešenie, pretože je taký kód ťažko optimalizovateľný, napríklad:

with({n:1}) var f = function(){return n++;};
Michal Augustýn
24. 8. 2009 22:45 Nový

Re: A co let?

celé vlákno

Proto jsem psal „Pokud se máme bavit o JavaScriptu obecně“.
A ano, bez použití letu je IMHO jediným způsobem, jak vytvořit closure, vytvoření další funkce.

_
_ (neregistrovaný) ---.privacyfoundation.de
25. 8. 2009 8:32 Nový

Re: A co let?

celé vlákno

Nie je to jediný spôsob, dá sa použiť with, no je to zlé riešenie:

function f(){
var i=1;
alert(i); // 1
with({i:2})alert(i); // 2
alert(i); // 1
}
f();
Dan
Dan (neregistrovaný) 77.78.87.---
18. 10. 2010 13:00 Nový

Re: Javascript a oblast působnosti proměnných - díl třetí

celé vlákno

Děkuji moc za tuto sérii článků, hodně mi pomohly objasnit kontexty v JS. Jen tak dál!

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