148 komentářů k článku Třídy, dědičnost a OOP v Javascriptu – I:

  1. gisat

    Odkdy funkce není objektem?

    léta působím jako javascriptový programátor a napsal jsem už mnoho článků o javascriptu a musím vám napsat, že jste to s tím vším nějak popletli.

    Odjakživa funkce byla objektem, z funkce jde vytvářet další objekty, pomocí prototypové dědičnosti lze objekty rozšiřovat. Veškeré objekty vycházejí z objektu Object a z něj vycházejí další vlastnosti, které jsou všem objektům stejné.

    Doporučil bych vám tímto pročíst si pár knih o OOP v Javascriptu, nebo si alespoň přečíst mé články na http://programovani.blog.zive.cz/category/javascript/

    Mám tam spoustu článků o OOP v Javascriptu a také mimochodem pětidílný seriál o funkcích v Javascriptu.

    Rozhodně za tři díly neopíšete celé OOP Javascriptu to ani náhodou. Tento článek je velmi nepovedený

    1. Daniel SteigerwaldAutor příspěvku

      Re: Odkdy funkce není objektem?

      Díky za komentář, kritiku vždy vítám. Avšak odříznu-li z vašeho komentáře úvod, reklamu na váš vlastní seriál, a dojem z mého, jediné co zbude je druhý odstavec, a ten je skoro totožný s mým textem. Čili, odkud jste vyčetl, že funkce není objekt?

      PS: zkusmo jsem se na na jeden díl vašeho seriálu podíval (http://programovani.blog.zive.cz/2009/08/javascriptova-vlastnost-prototype-3/)
      1) Nikdy nedeklarujte metodu v konstruktoru! (proč se dozvíte v druhém díle)
      2) Nikdy neprocházejte pole pomocí cyklu for in!!
      3) propertyIsEnu­merable je nespolehlivá metoda, nemá žádný smysl ji používat

    2. peter

      Re: Odkdy funkce není objektem?

      Som velmi rad, ze som nemusel to co pisete autorovi napisat ja, lebo osadenstvo zdrojaku by si zasa myslelo, ze kritizujem iba z principu.
      Plne suhlasim. Clanok je popleteny a matuci. Autor zrejme moc nechape OOP ale najma Javascript ako jazyk.

      Vsimli ste si, ze vsetci diskutujujuci, ktoru maju skutocne dobre IT vedomosti maju na zdrojaku auru okolo 10. :)

      1. Daniel SteigerwaldAutor příspěvku

        Re: Odkdy funkce není objektem?

        Super, takový komentář jsem si vždy přál :) Schválně, vypíchněte tři největší chyby v mém článku. Nemůžu se dočkat! :-)

        1. olin

          Re: Odkdy funkce není objektem?

          O to bych si moc neříkal. Já je sem zatím nepsal, protože článek i přes to má svou informační hodnotu :-)

  2. gisat

    Odpověď na dotaz Daniela Steigerwalda

    Danieli, odkaz na mé články o Javascriptu nejsou žádnou reklamou, pouze jsem Vás odkazoval na článek kde je proveden správný teoretický popis, i když to může vypadat namyšleně, já reklamu nepotřebuji, denně mi na blog chodí 150 až 700 návštěvníků. Také mé výtky neberte jako nějaké naparování či vychloubání se, tak to vůbec nemyslím.

    Chcete abychom Vám řekli o nedostatcích ve Vašem článku, takže za prvé, píšete: „Funkce, to je prostá definice. Není přiřazena k žádné třídě, k žádnému objektu“,
    že funkce jení objektem, je chyba, funkce je objektem, přebírá některé své „vrozené“ vlastnosti z objektu Object,tudíž je přiřezena k objektu Object v Javascriptu existuje dokonce objekt jako Function , z funkce tedy můžeme vytvářet objekty.

    Objekty totiž můžeme vytvářet buďto tím, že vytvoříme funkci například takto:
    function funkce(){}
    a tímto zápisem se obracíme na konstruktor funkce var x=new funkce();
    tečkovou syntaxí se pak můžeme obracet na jednotlivé proměnné funkce, objekt také můžeme vytvářet tak, že ho vytvoříme jako asociované pole. Ovšem vytvoření objektu jako asociované pole má svá omezení. Takový objekt můžeme nazývat literálním objektem.

    Tudíž tvrdit, že objekt je v Javascriptu asociované pole je špané. Dříve se objekty opravdu vytvářeli jako asociovaná pole, dnes se dají vytvořit i z funkce a je to častější způsob vytvoření. Dále pokud vytvoříte objekt z asociovaného pole tak nemůžete vytvářet novou instanci pomocí slova new.

    Dále píšete, nahoře, že funkce není objekt a dole zase že je.

    Dále píšete o Closure, ale všude se closure říká uzávěry. Dále se ještě jednou vrátím k objektům. Dále když už hovoříte o objektech bylo by velmi vítané kdybyste řekl, že existují vestavěné objekty, a dále že objekty si můžeme vytvořit vlastní například z funkcí nebo jako asociované pole.

    Celý popis funkce máte zmatečný, za prvé z funkce můžeme vytvářet objekt, funkce obsahuje proměnné a metody a můžeme ji nazývat třídou, na třídu se můžeme odkazovat konstruktorem pomocí slůvka new. Dále objekt window je globálním nejvyšším objektem vzhledem k DOM stromu dokumentu, nikoli k samotnému Javascriptu.

    Dále uvedené názvosloví je velice špatné, psát jako o špatné funkci je opravdu špatný způsob, měl byste psát o uzávěrách. Dále píšete o modulech, ve skutečnosti jde o prázdný objekt, že kterého nejde vytvářet další instance takto se skutečně dají vytvářet statické objekty.

    Opět jste špatně pochopil anonymní funkce. závorky před a za anonymní funkcí se dělají kvůli poli působnosti dané funkce, kvůli ničemu jinému se nedělají.

    Dále pokud se nepletu je jQuery totéž co $, a navíc se tyto proměnné dají přepsat na vlastní označení.

    Prostě celý článek je nepřehledný, nedůsledný, špatné názvy, špatně jste pochopil OOP v Javascriptu, jsou zde neúplné věci……

    Dále, proč bych nemohl deklarovat metodu v konstruktoru, pokud chci tuto metodu ihned zavolat tak ji tam můžu volat, nemusím ji psát jinam. Dále co se týče for in tak to skutečně nepoužívám, je to tam uvedeno pouze jako možný způsob.

    1. Aleš Roubíček

      Re: Odpověď na dotaz Daniela Steigerwalda

      Zkuste si ten článek přečíst ještě jednou. Daniel zde za ‚funkci‘ označuje něco co je samostatná funkce nevázaná na žádný scope (vyjma globálního) a nevolá se jako ‚konstruktor‘. Jde pouze o vysvětlení použité terminologie a proč pro jednu věc používá několik názvů.

      BTW Asociované pole != asociativní pole.

      1. peter

        Re: Odpověď na dotaz Daniela Steigerwalda

        Clanok je maximalne terminologicky paskvil. Nevhodny pre zaciatocnika, lebo mu nic neda a iba ho poletie. Daniel v clanku nevysvetlil ani ako funguje operator new (mozno to sam nevie) a uz tvori objekty ako divy.

        1. Aleš Roubíček

          Re: Odpověď na dotaz Daniela Steigerwalda

          OOP v JS není pro začátečníky a ani v článku nikde není nijak naznačeno, že je pro začátečníky určen.

          Osobně netuším, jaké projekty za sebou mají IT odborníci peter a olin, ale Danovu práci znám a vím, že on jen málo lidí má takové znalosti JavaScriptu jako on. Tak si prosím od cesty nechce poznámky typu „možno ani nevie ako operator new funguje“.

          1. pr.rybar

            Re: Odpověď na dotaz Daniela Steigerwalda

            > Danovu práci znám a vím, že on jen málo lidí má takové znalosti JavaScriptu jako on.

            Ak je toto pravda, optom sa asi dano nevie vyjadrovat primerane svojim vedomostiam. :(

      2. gisat

        Re: Odpověď na dotaz Daniela Steigerwalda

        Celé to tvrzení je mylné.

        Podívejte se na následující:

        function funkce(){}

        document.write(ty­peof(funkce));
        výsledek bude function

        document.write(fun­kce.constructor);
        výsledek bude Function() { [native code] }

        Z tohoto jasně vyplývá, že funkce je objektem typu function, konstruktorem funkce je Function() a Function vyplývá z objektu Object.

        Ovšem jiné je, když napíše, že funkci lze volat bez konstruktoru ale pokud vytvoří funkci z objektu Function tak lze funkci volat i konstruktorem.

    2. Aichi

      Re: Odpověď na dotaz Daniela Steigerwalda

      Pane, výrokem

      Opět jste špatně pochopil anonymní funkce. závorky před a za anonymní funkcí se dělají kvůli poli působnosti dané funkce, kvůli ničemu jinému se nedělají.

      jste vaší připomínku moc neozřejmil. Když vy můžete zkratkovitě soudit, budu i já. Pokud takto zmatkovitě píšete články, tak bůh s vašimi čtenáři.

      O jaké závorky vlastně jde? :)

      1. gisat

        Re: Odpověď na dotaz Daniela Steigerwalda

        jde přesně o toto:

        (functio(){
        tělo funkce
        })

        ty kulaté závorky na začátku a na konci jsou zde kvůli poli působnosti

        1. Aichi

          Re: Odpověď na dotaz Daniela Steigerwalda

          Můžete mi to vysvětlit? Co je podle vás pole působnosti? Ve článku se mluví o scope, je scope to co myslíte? Není náhodou scope omezen složenými závorkami, které ohraničují tělo funkce?

          1. gisat

            Re: Odpověď na dotaz Daniela Steigerwalda

            Velmi rád vysvětlím.

            Pole působnosti neboli anglicky Scope je trošku složitější téma než tady David nastínil.

            Prakticky by se dalo říct, že pole působnosti je dáno ve funkci složenými závorkami. Pole působnosti také například řeší kdy daná funkce má přístup k proměnným další funkce.

            Přístup k proměnným z jedné do druhé funkce mohou velmi krásně usnadnit uzávěry.

            Nechci být opět podezříván z reklamy, ale o poli působnosti a uzávěrách si můžete přečíst v mém článku zde: http://programovani.blog.zive.cz/2009/07/rozsah-pusobnosti-v-javascriptu-a-uzavery/

            Právě díky poli působnosti se doporučuje anonymní funkce uzavírat do kulatých závorek:
            (function(){})

            1. Aleš Roubíček

              Re: Odpověď na dotaz Daniela Steigerwalda

              Ty kulaté závorky ale nemají s polem působnosti nic společného. Z anonymní funkce se zde vytvoří objekt, který se potom dalším párem závorek zavolá.

            2. Daniel SteigerwaldAutor příspěvku

              Re: Odpověď na dotaz Daniela Steigerwalda

              Jmenuji se Dan, David je můj bratr ;). Nechci vás zklamat, ale to co píšete je hrubý omyl. Scope (pole působnosti, viditelnosti.. vida jak jsou ty překlady zrádné ;) generuje v Javasciptu pouze funkce. Mluvit o složených závorkách je zavádějící, generuje snad literální zápis objektu nějaký scope?

              var object = {foo: 'bla'}; // hle, složené závorky, ale žádný scope ;) 

              Podívejte se na tento kód:

              var a = function() {
                  document.title += 'a';
              } ();
              
              var b = (function() {
                  document.title += 'b';
              })();
              
              var c = new function() {
                  document.title += 'c';
              }; 

              Podstatné jsou ty kulaté závorky na konci (nebo operátor new ve třetím příkladě) Všechny příklady vytváří scope. Scope vytváří v Javascriptu funkce (nic jiného), a to pouze tak, že je funkce zavolána.
              Jak vidíte, v prvním příkladu kulaté závorky nejsou, a stejně funguje. Nicméně, důrazně doporučuji závorky vždy psát, a to čistě proto, že takový kód je pak čitelnější. Už na začátku je vidět, že je funkce uzavřena do závorek, takže se s ní chystám asi něco dělat. Třetí příklad zmiňuji jen pro zajímavost, používá jej třeba Dean Edwards.
              Pokud však funkci ničemu nepřiřazuji, tedy klasické:

              (function() {
              // ha, právě sem vytvořil nový scope
              })() 

              Kulaté závorky kol funkce, jsou skutečně nutné, avšak pouze kvůli syntaxi. Samy o sobě scope nevytvářejí, ani funkci nevolají.

              1. Farrell

                Re: Odpověď na dotaz Daniela Steigerwalda
                Chyba.

                [code]var x = (function() {return ‚x‘;})();[/code]
                žádný scope nevytvoří, jen předá návratovou hodnotu funkce obsaženou uvnitř, zde to je string ‚x‘

                Jde to udělat 50ti způsoby jako třeba…
                [code]
                function foo() {return ‚x‘;}
                var x = (foo)(); // x

                var foo = function() {return ‚x‘;}
                var x = (foo)(); // x

                var x = ((((((function() {return ‚x‘;}))))()));
                [/code]

                pokaždé bude v proměnné x string ‚x‘, něco jiného je ovšem tohle:

                [code]
                function foo() {this.test = ‚x‘;return ‚x‘;}
                var x = (new foo); // x

                var foo = new function() {this.test = ‚x‘;return ‚x‘;}
                var x = (foo); // x

                var x = ((((((new function() {this.test = ‚x‘;return ‚x‘;}))))));
                [/code]

                kde žádný string nedostaneme, nýbrž objekt, v každém případě. Závorky tam jsou jen na okrasu, abys věděl, že tohle opravdu na scope nemá vliv.

    3. jay

      Re: Odpověď na dotaz Daniela Steigerwalda

      Mno, kouknul jsem se na vaše stránky a na nejnovější článek. Tedy rozhraní v jazyku, který nemá typovou kontrolu je opravdu užitečná, ale fakt užitečná věc :-)).
      Jste si jistý, že víte o čem mluvíte?

      1. gisat

        Re: Odpověď na dotaz Daniela Steigerwalda

        Děkuji za kritiku :),

        narozdíl od Daniela mám všechny články logické, vykládající v souvislosti. O všem co tady Daniel píče tak o tom mám také články. Skutečně jeho článek je matoucí, nic neříkající. Například ta etapa s moduly, to co tam nazývá moduly jsou prázdné objekty.

        Pokud o tom nevíte, tak v Javascriptu se dají nasimulovat kroky a postupy OOP, které nejsou původně v Javascriptu vytvořeny. Jedním z nich jsou jmenné prostory které ve skutečnosti jmennými prostory nejsou. Rozhraní jsou možná v Javascriptu „šílenějším“ nápadem, ale i tak se používají, první díl celkem třídílného seriálu začíná od bezvýznamného vytvoření rozhraní z komentáře, kde kontrola není možná až po rozhraní kde kontrola možná je.

        Ve svých článcích se snažím lidem otevřít nový náhled na Javascript.
        Opravdu vím o čem píši mám za sebou ve světě internetu bohatou zkušenost v oboru Javascriptu.

        Nikoho své články nenutím číst. Pokud se vám nelíbí tak je nečtěte.

        1. jay

          Re: Odpověď na dotaz Daniela Steigerwalda

          Nic ve zlém, ale mě Danielův článek přijde docela pochopitelný i když nějaké nepřesnosti v něm jsou. Díky „pružnosti“ javascriptu a tomu, že není skutečně OO je ovšem i terminologie kolem něho dost pružná. Např. modul a prázdný objekt mě přijde jako stejný termínový problém jako třeba funkce a metoda.
          Ale k těm rozhraním, simulovat jmenné prostory v javascriptu má určitě smysl, protože pak omezím možnost konfliktů názvů, ale k čemu mě bude rozhraní?
          I pokud naimplementuje vlastní kontrolu, jestli objekt odpovídá rozhraní, tak se chyba odhalí až při běhu scriptu. Takže je to ve skutečnosti test, který se spouští při každém spustění scriptu. To mě nepřijde moc efektvní. Testy se běžně dělají jenom po změnách v programu (vím že např. v článku zmiňovaný Douglas Crockford podobné postupy taky popisuje, ale o jejich užitečnosti mě zatím nepřesvědčil).
          Ale možná mě něco uniká, mohl by jste prosím vás uvést odkaz na nějakou javascriptovou knihovnu nebo framwork, kde se rozhraní používá?

          1. MD

            Re: Odpověď na dotaz Daniela Steigerwalda

            Myslim ze resenim by bylo pouzivat jiny jazyk, ktery umi rozhrani (na rozdil od javascriptu) :-)

    4. Daniel SteigerwaldAutor příspěvku

      Re: Odpověď na dotaz Daniela Steigerwalda

      Vy jste si ten článek prostě nepřečetl poctivě, a většinu z toho co mi vyčítáte sem nikde nenapsal. Vezmeme to popořadě, a snad se nám společně podaří najít shodu.

      K druhému odstavci. Už vím, z čeho pramení vaše výtka. Vy totiž nevíte, co to znamená slovo přiřadit, anglicky assignment. Když píši „funkce není přiřazena“, rozhodně tím nemám na mysli, že funkce není potomkem Object. Je to jasné?

      Ke třetímu odstavci. Opakujete pouze co sem psal. Mimochodem, kdybyste článek nečetl tak ledabyle, věděl byste, že pokud voláme funkci s operátorem new, nikdy ji nepíšeme s malým písmenem na začátku (viz váš příklad). Operátorem new totiž voláme funkci, která je konstruktorem, a konstruktory se píší vždy s velkým písmenem na začátku.

      Čtvrtý odstavec. Objekt je v Javascriptu vždy asociativní pole, i kdyby jste se na hlavu stavěl. Ukažte mi jediný příklad, kdy v Javascriptu není objekt asociativním polem. Neukážete, protože žádný takový příklad neexistuje. Řekl bych, že jste si pojem asociativní pole spletl s pojmem object literal.

      „Dále píšete, nahoře, že funkce není objekt a dole zase že je.“
      Opět, neznáte význam slova přiřadit. Nikde sem nepsal, že funkce není objekt.

      „Dále píšete o Closure, ale všude se closure říká uzávěry.“
      Proč nepoužívám český pojem uzávěr, sem zmínil v úvodu. Není zažitý, a podle mého ani přesný.

      Nativním (vestavěným) objektům se věnuji v dalších dílech. Nepovažuji za nutné, správné, a ani možné, zmínit v prvním díle úplně vše.

      „Celý popis funkce máte zmatečný,“
      Já funkce nikde nepopisuji, takže nevím co máte namysli zmatečným popisem. Pouze osvětluji, kdy se funkci jak říká, protože to je pro následující text podstatné. Dále, Objekt a modul je to samé. Jestli je, nebo není prázdný, nehraje roli.

      Co se týká závorek. Vy prostě neumíte číst. Cituji sebe: „ty kulaté závorky na konci“. Co na tom nechápete? Ještě jednou: na konci. Nikde není napsáno: „Na obou koncích funkce“.

      K jQuery. Vždyť právě v tom svém příkladu ukazuji, jako použít closure anonymní funkce, aby bylo možné použít bezpečně $. Nechápu, co vám na tom příkladu vadí.

      No a závěrem, odpověď na vaši otázku: „Proč bych nemohl deklarovat metodu v konstruktoru“, naleznete v dalším díle. To, že si tak moc zkušený programátor, jakým bezesporu jste (a nemyslím to zle), tuto otázku vůbec klade, je mi důkazem, že mělo smysl článek napsat.

      1. MD

        Re: Odpověď na dotaz Daniela Steigerwalda

        Ke třetímu odstavci. Opakujete pouze co sem psal. Mimochodem, kdybyste článek nečetl tak ledabyle, věděl byste, že pokud voláme funkci s operátorem new, nikdy ji nepíšeme s malým písmenem na začátku (viz váš příklad). Operátorem new totiž voláme funkci, která je konstruktorem, a konstruktory se píší vždy s velkým písmenem na začátku.

        V popisu javascriptu, na ktery odkazujete na zacatku clanku, se mala pismena vesele uzivaji, viz https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Creating_New_Objects/Using_a_Constructor_Function

        1. Daniel SteigerwaldAutor příspěvku

          Re: Odpověď na dotaz Daniela Steigerwalda

          No vida, mají to tam špatně. Nic není dokonalé :) O co se tedy opírá mé tvrzení? Jednak je to samotná implementace Javascriptu ve všech prohlížečích. Všechny konstrukční funkce jsou psány s velkým písmenem na začátku (Array, Object, Function, Number, Boolean atd.), stejně tak statické objekty (Math).
          S malým písmenem na začátku se naopak píší všechny metody: (apply, call, toString, join, push, atd.), stejně tak všechny instance: (document, body, window, location).
          Z toho také vycházejí všichni autoři Javascriptových knihoven (yui, dojo, mootools, jquery…)
          Kde naopak úzus chybí, je psaní namespace. YUI preferuje PascalCase (Y.Object), Google closure vždy camelCase (goog.object).
          Důvod, proč konstruktory píšeme s velkým písmenem však nespočívá pouze v tom, že to tak dělají všichni, ale také proto, že nám velké písmeno naznačuje, že bychom měli použít operátor new.
          Jeden článek, v jinak velmi dobré referenční dokumentaci, na tom nic nezmění.

          1. Michal Augustýn

            Re: Odpověď na dotaz Daniela Steigerwalda

            Ano, je to tak – constructor function jedině s velkým písmenkem na začátku! ;-)

          2. MD

            Re: Odpověď na dotaz Daniela Steigerwalda

            No dobre, jde tedy ale jen o konvenci. Syntaxe je spravna i s malymi pismeny. Z vaseho popisu to vyznivalo tak, ze mala pismena jsou uplne spatne, error.

            1. Aleš Roubíček

              Re: Odpověď na dotaz Daniela Steigerwalda

              Porušování konvencí je mnohdy horší než error. Zatím co error se dá většinou dohledat a opravit, tak nedodržování konvencí je na přeshubu.

  3. Aleš Roubíček

    Pěkný článek + malá výtka k testům

    Ahoj Dane, pěkný článek, už se těším na další díly. Doufám, že to ostatním pomůže prorazit do JS stejně jako mně tvoje přednáška před lety. :)

    Mám jen jednu výtku. Stále dokola opakuješ, že privátní/lokální členy nejdou testovat. Pokud budu považovat testování = jednotkové testování, pak je tato vlastnost zcela žádoucí. Testování privátních členů je test smell. :) Privátní členy netestujeme, protože jejich chování se může měnit – ostatně proto jsou privátní. Funkčnost privátních členů testujeme pomocí chování objektu navenek. Pokud je nedokážeme v testech veřejného rozhraní otestovat, pravděpodobně jde o zbytečné členy… :)

    1. Daniel SteigerwaldAutor příspěvku

      Re: Pěkný článek + malá výtka k testům

      Díky Aleši za komentář, tuhle výtku sem popravdě čekal :) Ano, máš pravdu, privátní členy bychom testovat neměli, v ideálním světě. Sám ale píšeš: „Sice to je ukázka toho, že něco smrdí, ale stejně se to občas může hodit“. To je i můj názor. Kdyby článek byl vyčerpávají, musel bych dodat, neotestujete, protože Javascript žádnou reflexi na lokální členy nemá. Je jasné, že dříve nebo později se s nutností otestovat privátní členy setkáme. Prostě proto, že testy psané proti veřejnému API, by byly příliš vyčerpávající, nebo nepřesné. Pokud máš třídu chlap, s veřejnou metodou sbalHolku, a ta veřejná metoda volá privátní metody: vykoupej se, nauč se Gutha Jarkovského, atd., tak je rychlejší, přesnější a snadnější otestovat jednotlivé kroky, než slepě celou metodu sbalHolku. Kdybys ty metody schoval v closure, už je nikdy neotestuješ. Nicméně, testování zdaleka není jediným důvodem, jak ukáže druhý díl článku.

      1. Aleš Roubíček

        Re: Pěkný článek + malá výtka k testům

        Ano, psal jsem před dvěma a půl lety. :) Navíc u metod vykoupej se a nauč se Gutha Jarkovského není žádný důvod ke skrývání, tyto mohou být klidně veřejně vystaveny a tudíž jdou snadno otestovat.

        1. MD

          Re: Pěkný článek + malá výtka k testům

          Nevim, proc by mely byt verejne vystaveny, kdyz nemusi. Jen kvuli testovani? Zvlastni pristup…

          1. Aleš Roubíček

            Re: Pěkný článek + malá výtka k testům

            Páč asi se nebudete mýt pouze v případě že budete balit ženu, že? Stejně tak platí i druhý případ. U těchto metod není žádný důvod je skrývat a s testováním to nemá nic splečného. On je to totiž nešťastně zvolení příklad. Zbal ženu by bylo lepší implementovat jako Command pattern s injektovanou strategií. ;)

          2. Borek Bernard

            Re: Pěkný článek + malá výtka k testům

            To, že testy poněkud ovlivňují veřejné API, je běžné. Někdo to považuje za přirozené, někdo za špatné, ale změna API kvůli testům rozhodně není nic neobvyklého.

  4. Michal Augustýn

    struktura + ladění anonymních funkcí + těšení

    Daniel jistě ví o čem píše, ale bohužel mi článek přijde trošku blbě strukturovaný :( Např. dva způsoby implementace tříd proložené povídáním o „modulech“.

    Btw. kód:
    var foo = function () {};
    je opravdu neštastný, vzhledem k ladění. Tím se totiž vytváří anonymní funkce, která se přiřazuje do proměnné foo. Takže při ladění ve stack-trace uvidíte něco jako „anonymous_fun­ction125“ (záleží na konkrétní implementaci JS).
    Troufnu si tvrdit, že je lepší funkce pojmenovávat, tedy psát:
    var foo = function foo () {};

    Ale Javascript je tak bohatý jazyk s rozmanitými možnosti, jak zapsat jednu věc, že IMHO nejde napsat článek o JS, na kterém by si někdo něco „špatného“ nenašel ;-) Kolikrát i záleží na kontextu, ve kterém autor JS uvažuje (použití v prohlížeči, na serveru, v databázi, …).

    Nicméně se těším na další díly :) A přednášku na IDF :)

    1. Tom5

      Re: struktura + ladění anonymních funkcí + těšení

      Naprosto souhlasím s to nešťastnou strukturou.

      A nechávat si rozuzlení třídy na další díl, je také nevhodné. Pokud jsou uvedeny špatné příklady, měl by být hned uveden ten správný.

      1. Martin Malý

        Re: struktura + ladění anonymních funkcí + těšení

        Víte… ono to rozuzlení zabíralo v celém textu (cca 45.000 znaků) dobrou třetinu. Přemýšleli jsme s autorem, že bychom ho – právě kvůli takovým komentářům – vydali celý v jednom kuse, ale tak dlouhý text většina čtenářů „neučte“. Jediná možnost, jak nechat „správný“ postup v jednom článku se „špatným“, bylo jejich společné vydání (30.000 znaků). Jakýmkoli způsobem bráno se text vždy logicky rozpadal na „jak se to dělá a dělat nemá“, „jak se to dělat má a proč“ a „jak se to dá udělat elegantně“. Nakonec jsme usoudili, že čtenář ví, co je to „seriál“, a chápe, že ačkoli je každý díl logicky uzavřen, bude něco řečeno až příště…

        1. Karel

          Re: struktura + ladění anonymních funkcí + těšení

          1. Seriál nemá být psán stylem „tady máte jeden díl, ale zatím ho nečtěte, protože bez toho dalšího v tom budete mít akorát bordel“. Tento díl v žádném případě není „logicky uzavřen“. Spíše než odbornou publikaci váš seriál zatím připomína mexickou telenovelu – tak dnes jsme se nic nedozvěděli, ale v příštím díle se už Esmeralda určitě vdá!

          2. Buď jste měli oba (špatný i správný) postupy publikovat v jediném díle, nebo jste měli ten správný publikovat jako první. Psychologové už dávno vědí, že v člověku zůstávají hlavně první dojmy. Můžete do článku stokrát psát, že „takhle se to dělat nemá“, ale protože tu chybí jakékoliv srovnání (a jak se to tedy dělat má?), povedlo se vám v řadě lidí „zakotvit“ vámi uvedené „nesprávné“ postupy jako ty jediné správné (protože žádné jiné jste v článku neuvedl). To je síla podvědomí.

          3. Javascript neumím a ani se ho neplánuji učit. Článek jsem četl jen proto, že mně zajímá, jak jsou jednotlivé metodiky (zde OOP) implementovány v různých jazycích. Nemohu proto posoudit obsahovou správnost článku, ale pouze formální. A po formální stránce je to tedy opravdu průšvih.

    2. Ondřej Žára

      Re: struktura + ladění anonymních funkcí + těšení

      Zde jen kratka noticka: uvedeny zapis „var A = function B() {}“ je principialne spravny napad, ovsem v Internet Exploreru (6–8) timto vzdy vznika v globalnim objektu vlastnost B, nezavisle na hodnote A.

      Tedy, pokud treba pisu:

      MujNamespace.Tri­da.prototype.Me­toda = function Trida_Metoda() {}

      tak v IE bude najednou existovat window.Trida_Me­toda.

      1. Daniel SteigerwaldAutor příspěvku

        Re: struktura + ladění anonymních funkcí + těšení

        Opravím vás. Vlastnost B vzniká v aktuálním, ne globálním scope. Pokud tedy váš příklad zabalíte do vlastního scope, pomocí anonymní funkce například, globální scope zůstane netknut. Jinak nevýhody takového zápisu shrnuji v odpovědi na jiný komentář.

        1. Ondřej Žára

          Re: struktura + ladění anonymních funkcí + těšení

          Ano, máte pravdu, jedná se o aktuální scope. Nezávisle na tom však stále platí upozornění, že Internet Explorer (resp. JScript) se v tomto směru chová jinak, než ostatní implementace (nebál bych se dokonce použít termín „špatně“).

          Nakonec jsem si dovolil lehce upravit kus vašeho kódu, linkovaný z příspěvku http://zdrojak.root.cz/clanky/oop-v-javascriptu-i/nazory/7955/ (vyhodnocování shora dolů) – moje verze viz http://jsfiddle.net/zsBLH/. Je vidět, že i pojmenovaná funkce není ve scopu viditelná až do doby své deklarace – to proto, že vznikla jako „function expression“ a ne jako „function declaration“. Hezké počtení o této problematice viz https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Functions#Function_constructor_vs._function_declaration_vs._function_expression nebo http://yura.thinkweb2.com/named-function-expressions/.

    3. Daniel SteigerwaldAutor příspěvku

      Re: struktura + ladění anonymních funkcí + těšení

      Blbě strukturovaný.., asi ano ;) Možná by na začátku každého článku měl být obsah. Z něj by bylo snad patrné, že odbočka k modulům svou logiku má. Mluvím o hře na privátní členy, proto zmiňuji, že své využití mají pouze mimo dědičnost a třídy. Tedy pouze u modulů nebo globálních funkcí.

      K tvé připomínce. Ač je logická a správná, myslím, že vyvozuješ nedobrý závěr. Zkusme si porovnat klady a zápory obou způsobů:

      // tvůj způsob
      var foo = function foo() { };
      
      // versus můj
      var foo = function() { }; 

      Zápis, který považuji za jediný správný, tedy anonymní funkce přiřazená do proměnné foo, skutečně způsobí, že žádný ladící nástroj (Visual Studio, Firebug, Chrome debugger atd.) nemůže zobrazit název funkce. Kde by jej také vzal, že :)

      Avšak každý ladící nástroj, nás po kliku na řádek anonymous_function přenese na deklaraci funkce. Osobně se domnívám, že se s tím dá obstojně žít (a to jsou některé mé projekty velmi složité :)

      Nyní k záporům. První co mi vadí, je duplikace názvů. Dříve nebo později, bude třeba kód refaktorovat, a myslet na to, že je třeba vždy měnit název na dvou místech, mi přijde otravné (můj názor). Co mi přijde horší, je rozdílný způsob vyhodnocování viditelnosti takto deklarované funkce (mimochodem, není pravda co se píše v jiném komentáři zde, že funkce se stane globální).

      Kód se vyhodnocuje „odshora dolu“. Až dojde Javascript k var, proměnná foo se stane viditelná v celém svém scope. Ovšem než se Javascript pustí do samotného vyhodnocování, mrkne se, jestli v celém scope není nějaká funkce přímo pojmenována, a pokud ji nalezne, „zviditelní“ ji ihned.
      Nejlépe to osvětlí příklad: http://jsfiddle.net/Y7eRB/

      Nebudu argumentovat oblíbeným hypotetickým případem „něco si někde přepíšeme“, který je málo pravděpodobný, pokud zrovna nepíšeme program stylem plachta ;) Budu argumentovat tím, že až bude náš kód někdo číst, bude se lámat hlavu, proč je tam název určen 2×, a bude jej to rozptylovat od práce. No a nakonec, neznám knihovnu, ani komponentu, která by tento styl používala.

      Jak vidíš, je to trade-off. Pokud trváš na svém způsobu, dobře. Buď pak ale důsledný, a používej jej všude. A donuť i všechny ostatní programátory ve svém týmu, ať jej také používají ,–)

      1. Michal Augustýn

        Re: struktura + ladění anonymních funkcí + těšení

        Teď je správný čas použít mou větu Kolikrát i záleží na kontextu, ve kterém autor JS uvažuje (použití v prohlížeči, na serveru, v databázi, …).
        Mé použití JavaScriptu je ale opravdu velmi speciální (vyžadovalo i nějaké hooky v samotné implementaci)…:D

      2. Aleš Roubíček

        Re: struktura + ladění anonymních funkcí + těšení

        MS AJAX to v debug verzi používá, je díky tomu přehlednější call stack při debugování. Jindy to opravdu význam nemá.

      3. mizuki

        Re: struktura + ladění anonymních funkcí + těšení

        ve vami uvedenem priklade ale pouzivate „function foo () {„, proto se to chova jinak. pri pouziti „var foo = function foo() {“ se chova samozrejme stejne jako „var foo = function() {„…

  5. MD

    funkce objekt/neobjekt?

    Nelibi se mi, ze nahore pisete, ze vsechno je objekt (i funkce) a ma spolecneho predka Object. Nize pisete, ze funkce je prosta definice a ze neni prirazena k zadnemu objektu. Tak jak tomu mam rozumnet?

    1. Ondřej Žára

      Re: funkce objekt/neobjekt?

      „Neni prirazena k zadnemu objektu“ – tim autor mysli (alespon ja to tak chapu), ze funkce ve smyslu metody (tedy takova, ktera bude volana s teckou pred nazvem) neni svazana s tridou, u ktere je definovana.

      Zatimco tedy v jinych jazycich piseme

      class A { public method B() {} }

      a je tak patrne, ze B „patri“ k A, tak v JavaScriptu zapis

      A.prototype.B = function() {}

      nevytvari zadnou logickou vazbu mezi (zcela normalni) funkci B a jeji (tridou) A. Uplne stejneho vysledku by bylo mozno docilit treba zapisem

      var B = function() {}
      A.prototype.B = B;

      B je stale normalni funkce bez jakekoliv vazby na A.

    2. Daniel SteigerwaldAutor příspěvku

      Re: funkce objekt/neobjekt?

      Je to jednoduché. Snažím se vysvětlit, kdy se funkci říká funkce, kdy metoda, a kdy konstruktor. To pojmenování nám odlišuje, jakou roli funkce zrovna hraje. Když říkám „funkce je prostá definice a není přiřazena k žádnému objektu.“ tak to prostě znamená, že kdybychom funkci přiřadili třeba do prototype, už bychom jí správně měli říkat metoda. Mrkněte se na definici metody. „A method is a subroutine that is exclusively associated either with a class“. Už je to jasné?

  6. Mazarik

    clanok

    Konecne sa objavil na zdrojaku po dlhom case clanok, ktory ma zaujal a prijemne prekvapil. S obsahom clanku suhlasim, aj ked si myslim, ze by to mohlo byt troska viac do hlbky, aby si pripadni programatori v js uvedomili, co sa ma pouzivat na co a ktore techniky su uplne nevhodne a preco. Js je totiz tak amorfny a ma tolko implementacii, ze zaciatocnici maju s jazykom velke problemy(tiez som ich mal a niektore dnes este mam:). Samozrejme by sa tym clanok predlzil a bol by asi nezazivnejsi a mohlo by to ludi odradit od citania.

    1. Daniel SteigerwaldAutor příspěvku

      Re: clanok

      Díky za komentář. Článek sem původně napsal v jednom kuse. Ale z důvodu délky mi byl rozdělen do třech dílů. Co se týká amorfnosti a množství implementací, souhlasím s vámi. Právě proto sem začal popisem špatných technik. Druhý díl se bude věnovat správné implementaci, snad vás mile překvapí.

  7. fos4

    povedený článek

    Moc povedený článek, už se těším na pokračování.
    Autora se chci zeptat jestli na konferenci internet developer forum bude obsah jeho přednášky stejný jako tento seriál. Díky

    1. Daniel SteigerwaldAutor příspěvku

      Re: povedený článek

      Ano bude. Na přednášce navíc půjdu více do detailů, a samozřejmě bude prostor pro otázky a diskuze.

  8. logik

    Pochvala

    Steigerwald: Přestože ten článek někdy je trochu zmatený (což nekritizuju, protože z principu javaskriptu snad každej článek o něm musí bejt zmatenej), tak až na detaily i přijde velmi dobrý.

    Hrebenar: Promiňte, ale většina vašich výtek je mimo, zřejmě jste článek poněkud nepochopil. Ale stejně smyslem Vašeho komentáře bylo získat více prokliků na Vašem blogu a ten zcela určitě splnil.

    (abych byl adresnej, tak např. u modulu závorky kolem a za anonymní funkcí jsou nutný, protože je potřeba tu funkci zavolat – jako modul neslouží ta samotná anonymní funkce, ale právě tím voláním vytvořené closure společně s
    vrácenou funkcí

    Nebo že objekt není asociativní (nebo asociované :-D) pole? Ono snad v JS nejde napsat funkce[‚a‘]=? Co se mění na pravdivosti tvrzení: „každý objekt je asociativní pole,“ se mění tím, že se dnes většinou objekty vytvářejí ze speciálního asociativního pole, které lze ještě navíc zavolat?

    Nebo ad jQuery – uvedené řešení je jednoduchá berlička pro to, aby kód fungoval i když jiná knihovna přepíše $ definovaný v jQuery. Opět jsou v příkladu všechny závorky nutné.

    Shrnul bych to takto: Zatímco autor tohoto článku byť někdy malinko neobratně se snaží vysvětlit jak javascript funguje uvnitř a teprve z toho vyvozovat závěry, vy jste jaksi spoután svým poněkud omezeným viděním javascriptu a
    hlubší porozumění zaměňujete za chybu…

  9. aprilchild

    vyborne

    Pro ty, co to cetli 3× a stejne sotva pochopili – poslouchejte steidu (autor), jestli nekdo vi, o cem ve svem oboru mluvi, je to on. Tech par kritiku je typicka trolli zumpa, kterou se netreba zabyvat.

  10. Martin Staněk

    pohled na článek

    Nevěnuji se programování ecmascriptu zase tolik, ale v poslední době jsem se o možnosti OOP zajímal. Chtěl bych Vám nabídnout můj pohled na věc, co bych vlastně očekával od úvodního článku.

    Psát pro širší publikum není snadné, ale stačí dodržovat některé základní postupy při psaní, které produkují lepší výsledky. Když se podívám na strukturu Vašeho článku, tak na první pohled vidím, že jste na ní příliš nepřemýšlel a psal jste, co vás napadlo. Je třeba začít osnovou a pak postupně formovat článek.

    Především by na úvod neškodilo zmínit, co je vlastně míněno tím OOP v ecmascriptu se srovnáním, jak je to vnímáno jinde (rozhodně najdeme rozdíly v chápání OOP v ecmascriptu a smalltalku). Jeden odstavec by si to zasloužilo.

    Rozhodně bych se vyvaroval nějakému přehledu pojmů, myslím si, že je vhodné vysvětlit pojem ve chvíli, kdy je potřeba a s krátkým příkladem. (Ty tam sice obvykle máte, ale docela by mě zajímala statistika kolik lidí na ně opravdu kliklo)

    Celkově ten článek působí neuceleně, psaný horkou jehlou, což je zřejmé i z povahy diskuze, kdy jsou zpochybňovány Vaše znalosti. Také nesprávně.

    Doufám, že si do příštích dílů z diskuze něco odnesete. Toto téma mě velice zajímá a rád bych se o OOP v JS dozvěděl, co nejvíce.

    1. aprilchild

      Re: pohled na článek

      Nic ve zlem, ale nebylo by jednodussi priznat si, ze mi dela potize napoprve pochopit psany text? A v case usetrenem psanim zbytecneho komentare zkusit precist pecliveji jeste jednou? :)

      Dan uz z povahy veci nepise pro siroke publikum, tema neni jednoduche, pokud vas to zajima – v klidu ctete a studujte, a na komentovani alespon na chvili zapomente.

      Ano, i muj prispevek je zcela zbytecny.. :)

      1. Martin Staněk

        Re: pohled na článek

        Je vtipné, že mi vnucujete studium, když vůbec netušíte, jaké znalosti mám nebo nemám. Nevím čím jsem podle vás dal najevo, že bych článek nepochopil. Můj komentář nabídl pohled na formu článku pro autora. Dobře napsaný článek na téma OOP v Javascriptu si představuji jinak.

        Pokud Dan nepíše pro široké publikum, tak by neměla téměř celá první polovina článku obsahovat naprosté základy jako co je to objekt, kontext nebo scope. Pokud to čtenář neví, tak nemá smysl, aby ten článek vůbec četl. Je třeba přemýšlet nad tím koho chci oslovit.

        Souhlasím s vámi, váš příspěvek je zbytečný ;)

        1. Aleš Roubíček

          Re: pohled na článek

          Jenže začátek článku není vysvětlení základů, ale definice použité terminologie. Je vidět, že jste to, stejně jako většina diskutujících tady, ještě nepochopil. Což je smutné.

        2. karmi

          Re: pohled na článek

          > když vůbec netušíte, jaké znalosti mám nebo nemám.

          No, možná, že jste s tím po zdejším obyčeji začal sám a docela zhurta:

          >> Když se podívám na strukturu Vašeho článku, tak na první pohled vidím,
          >> že jste na ní příliš nepřemýšlel a psal jste, co vás napadlo.

          WTF? Tady na Zdrojáku se s železnou pravidelností vyskytují jasnovidci. Autor „psal, co ho napadlo“…

          >> Především by na úvod neškodilo zmínit, co je vlastně míněno tím OOP (…)

          Ale. To je docela laciná „kritika“, ne? (Ta debata s pány gisat, peter, atd o něco výše, to není kritika, ale komika. Taková řekněme „krampolovská“.) To bychom si taky mohli začít vykládat že JavaScript se původně jmenoval _Mocha_ atd atd atd.

          >> (…) vyvaroval nějakému přehledu pojmů (…)

          Z kontextu článku je ale zjevné, že _právě_ přehled pojmů na začátek je potřeba, včetně vysvětlení, proč je dle autora lepší anglické pojmy _nepřekládat_ do češtiny. Neboť většina žabomyších hádek okolo JS u nás se zamotá už v tom, že _scope_ nazývá každý nějak jinak a především tomu vlastně na 100% nerozumí, ale rozumí tomu jen trošičku a o tu trošičku se taky bude hádat.

          Článek je vynikající. Těším se na další díly. Je nesmírně osvěžující přečíst si něco a přímo fyzicky v tom _vidět_ to porozumění věci. To se stává zřídka.

          (Už jsem třikrát smazal nějakou reakci na místní jasnovidce a kritiky, tak tentokrát již odešlu. Aby to nevypadalo, že to tady čtou jenom mašíblové.)

    2. Daniel SteigerwaldAutor příspěvku

      Re: pohled na článek

      Martine, článek se původně jmenoval „Třídy, dědičnost a OOP v Javascriptu“, ale titulek mi byl zkrácen, a článek samotný rozdělen do tří částí. To se nemohlo nijak neprojevit ;)
      Srovnání rozdílu s klasickými třídami jsem slíbil v úvodu, a článek jej obsahuje, v druhém a třetím dílu ;)
      Nebojte se, dovíte se vše podstatné.. seriál je už napsán. První díl berte jako takový úvod. Nechtěl sem čtenáře zahltit pojmy jako agregace, mixování, dědičnost, volání přepsané metody, atd.

      1. Martin Staněk

        Re: pohled na článek

        To je celkem škoda, protože ten titulek vystihuje téma mnohem lépe a taky by nedošlo k některým nedorozuměním. Až bude celý seriál venku, tak určitě bude působit kompaktněji. Díky

  11. s

    Oh!!

    Jsem ohromen. Tohle nepamatuju, nemam horkost? Teplota v analu… 36.6? V norme. Rooote! Nezblaznil ses? Zrak ok, alkohol v krvi v norme… Kurwa, ja ten clanek precet az do konce. Chapete to? Ja to precet az _DO_KONCE_ Hrabu se, hrabu, hrabu, hrabu… Kde se asi muzu hrabat? V pameti se hramu. A nejak se nemuzu dohrabat. Kdy se vam naposled stalo, ze byste tu neco docetli az do konce?

    Dane, chvalit te nebudu, protoze bys spychnul a pokracovani uz bych pak treba nedocet. Kazdopadne, mas me simpatie. :-)

    1. Michal Augustýn

      Re: Oh!!

      A já přečetl tenhle názor až do konce, protože jsem byl zvědavý, jaké bude rozuzlení :D

  12. Rene

    Článek

    Javascript aktivně nepoužívám, rád ho nemám, ale přesto jsem článek přečetl jedním dechem :).
    Takže Dane, jako prostý laik ti děkuju za článek, odborníci na JS ti v komentářích určitě ještě každou větu rozcupují, aby se jim lépe spalo.

    Blízkost hnoje přitahuje masařky, blízkost Rootu evidentně hovada.

    Dříve platilo, že co Čech, to muzikant. Dnes, co Čech, to evidentně expert na javascript. A všichni JS experti si dnes dali sraz na Zdrojáku.:)

  13. v6ak

    Proč privátně?

    Pokud se vykašlu na privátnost, pak může nastat problém u potomků, které přeci nemusí zajímat, jaké mám privátní vlastnosti a metody, ne?

    Samozřejmě, v případě preference kompozice před dědičností (správně) to je většinou OK, ale chtěl jsem ukázat, že privátní viditelnost má smysl nejen co do dokumentace.

    OT: Dál bych byl v seriálu rád za nějakou budoucí zmínku o volání parent konstruktoru.

    1. Daniel SteigerwaldAutor příspěvku

      Re: Proč privátně?

      Položil jste velmi dobrou otázku, a já jsem za ni rád. Přesně takovéhle dotazy obohacují článek. Nejprve ale odpovím na OT: Ano, ve druhém i třetím díle si ukážeme správné (i špatné) volání nejen parent konstruktoru, ale i libovolné jiné, třeba přepsané, metody.

      Teď k těm privátním. Nerad bych předbíhal, ale potomek nikdy nezavolá privilegovanou metodu kterou, jak jsme si už řekli, používá Crockford k přístupu k privátním proměnným. Nezavolá, protože metoda začne existovat, až v okamžiku vytváření instance, čili, není součástí prototype. Museli bychom vždy povinně volat rodičovský konstruktor, nebo to nějak hacknout (že to lze prasácky nějak obejít, to nechci ani naznačovat ;)

      Můžete namítnout: „A co když metoda sama bude privátní?“ To je případ, který záměrně ve výkladu nezmiňuji. Považuji jej totiž za zbytečný, náchylný k chybám, a svádějící k falešnému pocitu nějakého cool zabezpečení kódu. Je to relikt z ostatních jazyků, který dle mého jde proti duchu Javascriptu, a jehož použití je oprávněné pouze v příkladu s jQuery, microoptimalizací, a podobných vzácných případech. Přesto, jednu implementaci vám ukáži. Podívejte se na tento příklad, ale neberte si z něj příklad ;) http://jsfiddle.net/8EtRB/
      Máme kvazi-privátní (ve skutečnosti lokální) metodu toString. Jestli je instanční, nebo statická, závisí na tom, jak metodu voláme. Takto definovaná metoda, může i využívat nějaké privátní statické proměnné, případně manipulovat přímo s instancí, pokud ji instanci předáme. Co je na tom příkladu tedy zlého? Za prvé, jedná se o zásadně jiný zápis. Zatímco v jazyce, který privátní členy podporuje klíčovým slovem private stačí použít klíčové slovo, zde musíme využít closure. Kód se bude hůře refaktorovat. Za druhé, tento zápis nejde změnit, což by nám později vadilo (v posledním díle si ukazujeme jak deklarovat s třídy nejen správně, ale i úsporně). Za třetí, a to je hlavní důvod, je to zcela zbytečné. Proč bych měl v jazyce jako je Javascript něco zapouzdřovat?

      1. v6ak

        Re: Proč privátně?

        Já reagoval na „Mírně to naznačíme podtržítkem v názvu, brutálně pomocí closure. Jestli někde má smysl simulovat privátní proměnné pomocí closure, tak jedině u statických objektů, tedy modulů.“.

        BTW: Poslední způsob vytváření třídy taky není zrovna chválen, ale věta „Ukážeme si dvě falešné a jednu správnou.“ napovídá, že by to mohl být ten správný. Asi by to chtělo trošku korekci srozumitelnosti. Já vím, asi to bylo myšleno tak, že to není správný způsob, ale vznikají při něm skutečné třídy.

        1. Daniel SteigerwaldAutor příspěvku

          Re: Proč privátně?

          Sakra to jsou zmatky, měl sem seriál od začátku psát na limit délky jednoho článku, a ne čekat, že to půjde nějak dobře rozdělit ;) Ne, ani poslední uvedený způsob není správný. Správnému způsobu bude věnován celý druhý díl :)

          1. v6ak

            Re: Proč privátně?

            To je celkem jasný. Já ze článku pochopil (nečetl jsem úplně důkladně, něco znám), že správný způsob budou asi ta podtržítka. A na to byla ta moje reakce.

            Jinak za informace o parent constructor call děkuju předem.

      1. Daniel SteigerwaldAutor příspěvku

        Re: Proč privátně?

        A už sis jej opravil? ,–)) Koleduješ si o brutální review :)

        1. Daniel SteigerwaldAutor příspěvku

          Re: Proč privátně?

          Jinak, abys mne špatně nepochopil, článek je dobře a poctivě napsán. Jen obsahuje několik strašlivých chyb :o)

          1. Michal Augustýn

            Re: Proč privátně?

            Já vím ;-) Některé jsem si uvědomil s odstupem času, ještě dřív, než jsi začal rýt ;-)
            Review, resp. přepis bez chyb, jsem právě plánoval tady na Zdrojáku, ale teď mám obavu, že mi to nepovolí, aby tu nebylo přejavascriptováno… Tak asi radši napíšu něco o ASP.NET MVC :o) Ať Ti nelezu do zelí :)

            1. junix

              Re: Proč privátně?

              No, prave pasaz o dedicnosti je v tvem jinak dobrem clanku slabinou. Tvrzeni, ze dedicnost v JavaScriptu neexistuje je jadrem problemu. Za takoveho predpokladu by byl i tvuj zpusob volani konstruktoru predka dobrym zpusobem, jak si dedicnost doplnit.

              Jenze Javascript dedicnost primo podporuje. Tu prototypickou. O ni a o problemech, ktere nam prinasi – prototyp vs. inicializace instance – bude pocitam pristi dil, takze bych uz v tomto tematu dale nepredbihal :)

  14. David

    Struktura článku

    Souhlasím s Martinem Staňkem, že by si článek zasloužil lepší strukturu. V žádném případě nechci zpochybňovat znalosti autora o JavaScriptu (je vidět, že je má), ale stylisticky působí článek trochu zmatečně. Vedle toho bych chtěl poukázat na větu:

    „Douglas Crockford udělal pro svět Javascriptu hodně, ale některé články, věnované OOP a dědičnosti, se mu zrovna nepovedly.“

    Nevím kde autor bere tolik sebevědomí, že kritizuje Douglase Crockforda, senior JavaScript architekta firmy Yahoo! a člena komise, která určuje vývoj jazyka JavaScript, za jeho články. Nechci být hrubý, ale možná by si měl autor sednout na prdel a zamyslet se nad vlastními články.

    1. Daniel SteigerwaldAutor příspěvku

      Re: Struktura článku

      Autor na prdeli sedí více než je zdrávo, a věřte že seriál by nepsal, kdyby si svá tvrzení nemohl obhájit.

      Uvidíte, že na konci seriálu se mnou budete souhlasit ,–) Vždyť i Crockford sám přiznává, že jeho začátečnické pokusy byly pomýlené. („… now I see my early attempts to support the classical model in JavaScript as a mistake.“) A to se týká nejen odkazovaného článku, ale třeba i tohoto, nebo tohoto. Jeho články jsou plné falešných a zbytečných doporučení, jeho techniky dědičnosti a OOP, jsou ošklivé jak hřích. (krom jedné jediné)

      Pochybujete? Tak jak vysvětlíte, že YUI (oficiální Yahoo framework), ve své poslední verzi žádné jeho techniky nevyužívá? Dokonce ani oblíbenou manýru zvanou: Modul S Konečně Supr-Dupr® Privátními Proměnnými™.

      1. David

        Re: Struktura článku

        Děkuji za odpověď. Články, které uvádíte, jsem četl, a i přesto, že Crockfordovi původní techniky se v moderních frameworcích už nepoužívají, stále mají články s jejich popisem velkou informační hodnotu a v žádném případě bych je nepovažoval za „nepovedené“. Naopak v nich lze vyčíst postupný rozvoj programovacích technik používaných v JavaScriptu.

        V každém případě rád vidím články o JavaScriptu na Rootu a těším se na pokračování seriálu.

  15. Bauglir

    Špatný článek

    Pamatuju ještě černý Root, ale na takhle špatný si nemohu vzpomenout

    1/ JS samozřejmě třídy nemá, citovat wiki a ještě takovou hloupost je úsměvné, to je definice pro někoho, kdo nikdy o OOP neslyšel. Programátor musí vědět, co to znamená „třídní programování“: zapouzdření, dědičnost a polymorfismus, přičemž JS poslední 2 vlastnosti neobsahuje. To, že se dají obejít (rozšiřováním předpisů, přiřazování prototypů) ještě neznamená, že má třídy. JS má typy, má objekty a nikdy nemělo třidy. Když už píšete články pro programátory, citujte alespoň z trochu relevantních zdrojů, jako například specifikace ECMA (http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf), strana 3: ECMAScript does not use classes.
    To, čím se JS tolik liší od ostatních jazyků je právě neexistence tříd, ale existence prototypů. Neexistují klasické třídy a neklasické třidy.
    Pojem tříd a instancí nemá v článku žádný význam, pokud to někdo chce číst v souladu s realitou a správně, čtěte typy a objekty.
    Věty jako „Falešné, protože ve skutečnosti nejde o vytváření instancí tříd, ale o konstrukci podobných objektů.“ jsou potom už jenom vtipem.

    2/ JS nemá nic takového, jako primitivní typy, to, že mžete napsat
    var num = 5;
    je jenom deklarací objektu typu Number jeho literálem, pokud by se jednalo o primitivní typ, následující konstrukce by nebyla možná:

    var a = {'num': 5};
    alert(a.num.toString());

    věřte, že funguje skvěle

    3/ Následně se článek bohužel už věnuje „třídám“ a „instancím“ a z tohoto hlediska ho nemá smysl číst.

    Bez ohledu na to, jak dobrý je pan Steigerwald programátor, tak jeho způsob prezentace a vysvětlování JS je strašný a dělá JS medvědí službu. Každý, kdo se kdy setkal s třídami v OOP se musí při seznamování s JS dozvědět hned na začátku jednu věc: JS třídy nemá, zapomeň na OOP tak, jak ho znáš z jiných jazyků. JS má prototypy a ty nemají s třídami nic společného.

    1. David Grudl

      Re: Špatný článek

      Špatný komentář, ale zdaleka ne nejhloupější zde :-)

      ad 1) pokud je definicí třídního programování zapouzdřenost, dědičnost a polymorfismus, znamená to, že např. Python, který nemá zapouzdření členů tříd, není „třídním“ jazykem? To by bylo hodně odvážné tvrzení, co?

      ad 2) budete velmi překvapen, ale typeof num nevypíše Number :-) (na velikosti záleží). Dokonce si můžete vyzkoušet, že čísla jakožto primitivní typy se do funkcí nepředávají referencí, narozdíl od objektů. Atd.

      1. pr.rybar

        Re: Špatný článek

        Špatný komentář, ale zdaleka ne nejhloupější zde :-)

        1) Medzi jazykmi Python a Javascript je dooost velky rozdiel co sa tyka tried. Python triedy ma a Javascript nie.

      2. koroptev

        Re: Špatný článek

        dle meho intuitivniho citeni, ktere ma asi tak stejnou vahu jako vase neduvera v odvahu vami nastineneho potencialniho tvrzeni, je jazyk bez zapouzdreni (ale s dedicnosti a plymorfismem at uz to znamena cokoli) vice tridni nez jazyk bez dedicnosti..

        jinak si tez myslim, ze tridni jazyk je ten, jehoz OOP je zalozeny na tridach, coz JS neni

        a kamenujte me

      3. peter

        Re: Špatný článek

        Neviem ake su Vase znalosti jazykov Python a Javascript, ale skutocne Javascript triedy na rozdiel od Pythonu nema. Kde ste videli triedy v Javascripte?

    2. Daniel SteigerwaldAutor příspěvku

      Re: Špatný článek

      Pane Bronislave Klučko (jste to vy: http://www.bauglir.com, že?), spravedlivý hněv vás zaslepil, ale to nevadí, to se občas stane každému.
      Váš komentář vítám, protože mi dává příležitost opět vyvrátit pár omylů. Pojďme si je tedy rozebrat. Opakování je matka moudrosti ,–)

      1) Je častou chybou programátorů začátečníků, brát všechny pojmy dogmaticky. Možná vás to překvapí, ale co platí v jednom programovacím jazyce, nemusí platit v jazyce jiném. Jedním z takových pojmů je třída. Každý jazyk ji definuje po svém, a Javascript není výjimkou. V úvodu, který jste určitě bleskem pouze přelétl, už už aby jste mohl komentovat, jsem zdůrazňoval, že jde o konsensus mezi autory Javascriptových knihoven. Koukněte: dojo, mootools, yui, google closure, prototype, qooxdoo. Všichni hovoří o třídách. Za třídu se v Javascriptu označuje konstrukční funkce, používající vlastnost prototype. Už vidíte, jak moc se mýlíte?

      Mimochodem, když už chcete citovat ze specifikace, poprosil bych o celou větu až dokonce. Ta zní: „ECMAScript does not use classes such as those in C++, Smalltalk, or Java.“ Hned to zní jinak, že? :-) Dokonce i specifikace mluví o třídách, pouze zdůrazňuje, že jsou jiné.

      2) Javascript samozřejmě primitivní typy má. Když už tu mlátíte specifikací o stůl, tak si snad zvládnete i dohledat větu: „A primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String;“. Vy ale zcela evidentně nevíte, co primitivní znamená. Vážně jste si nikdy nevšiml, že se v Javascriptu některé typy předávají referencí, a jiné hodnotou?

      Byl bych k vám krutý, kdybych nevysvětlil, jak váš příklad ve skutečnosti funguje.

      var num = 5; 

      Tento zápis skutečně deklaruje primitivní hodnotu. Zkuste předat num do nějaké funkce, tam jej inkrementovat. Změní se původní num? Nezmění, protože je primitivní a byl tedy předán hodnotou. Dále si můžete vyzkoušet přiřadit nějakou hodnotu:

      var num = 5;
      num.a = 1;
      alert(num.a)​ // undefined 

      Sakra, nejde to. Proč? Protože num je primitivní :-D

      Jiná situace by byla, pokud byste napsal:

      var num = new Number(5) 

      S takto vytvořeným číslem můžete pracovat stejně jako s jeho literárním zápisem, avšak pozor, num se předává referencí. Schválně si to zkuste, protože je to pro vás evidentně nová věc. Pomalu se blížíme v rozuzlení vašeho (krapet ukecaného) příkladu. Proč ukecaného? Protože stejného výsledku dosáhneme i takto:

      var num = 5;
      alert(num.toString())​ 

      Jak je vidět, ani nemusíte vytvářet objekt ‚a‘ :-)

      Shrnutí. Literární zápis generuje primitivní hodnoty, zatímco zápis pomocí konstruktoru (Number, Boolean, String) objektové reprezentace. Převést primitivní hodnotu na její objektovou reprezentaci, lze pomocí přímého volání konstruktoru, ani nemusíme použít new.

      var num = 5;
      var objectNum = Number(num); 

      Obráceně to za nás Javascript udělá vždy, když detekuje, že by se primitivní hodnota hodila, nebo to lze provést explicitně, a jak ukazuje poslední alert, dokonce můžeme používat vlastní objekt, číslo imitující.

      var objectNum = new Number(5);
      alert(objectNum + 2); // 7
      alert(objectNum.valueOf() + 2); // 7
      var customNumber = {
          valueOf: function() {
              return 5;
          }
      };
      alert(customNumber + 2); // 7
      ​ 

      Za domácí úkol si spočítejte, kolikrát je pojem ‚primitive‘ zde uveden.

      3) K poslednímu bodu bych dodal, že právě Vy, byste si měl článek poctivě pročíst, a to ve svém vlastním zájmu.

      1. xx

        Re: Špatný článek

        > Je častou chybou programátorů začátečníků, brát všechny pojmy dogmaticky.

        Problém je v tom, že když nepoužíváte přesné a jasné definice základních pojmů, tak se pak vlastně neví, o čem mluvíte. Odstrašujícím příkladem může být pojem OOP. Když někomu řeknete, že jazyk XYZ podporuje OOP, tak je to jako byste nic neřekl (možná říkáte, že jazyk podporuje dynamic dispatch, ale to je asi tak všechno).

        1. pr.rybar

          Re: Špatný článek

          Aj ja som za striktne definovanie a dodrziavanie pojmov. Je to znak profesionality.
          Kto sa nevie vyjadrovat, nech nepise clanky, lebo narobi viac skody ako osohu.

          1. Jakub Nešetřil

            Re: Špatný článek

            A já ne. Dogmatické a striktní chápání jakéhokoliv pojmu vidím jako programátorovu slabinu a jeho neschopnost. Místo chápání konceptů se brání definicemi pojmů.

            Dobrý programátor je schopný používat koncepty a dokonce o nich i komunikovat s ostatními bez takovéhleho dogmatismu.

            Dan Steigerwald je jeden z nejlepších JS programátorů v Čechách a článek který napsal čouhá nad českým průměrem znatelně. Možná snad jen to je jeho chybou – tedy že je článek určený inteligentním, uvažujícím lidem.

            1. pr.rybar

              Re: Špatný článek

              > Dogmatické a striktní chápání jakéhokoliv pojmu vidím jako programátorovu slabinu a jeho neschopnost. Místo chápání konceptů se brání definicemi pojmů.

              Ako mozete chapat koncept, ked nechapete pojmy?

              > Dobrý programátor je schopný používat koncepty a dokonce o nich i komunikovat s ostatními bez takovéhleho dogmatismu.

              Mam pocit ze Vy asi inak chapete aj moju vetu „striktne definovanie a dodrziavanie pojmov“. To potom ale vedie na styl diskusie „Ja o voze, ty o koze“, co je presne teraz nas pripad.

            2. Bauglir

              Re: Špatný článek

              Dogmatické chápání pojmů je základem, protože (teď nemluvím o panu Steigerwaldovi, dávám obecné příklady) když si někdo bude plést proměnnou a typ, funkci a metodu, hodnotu proměnné a pointer na proměnnou, a já nevím, co ještě, tak to není dobře. Uvědomte si, že toto všechno nejsou jen tak pojmy něčeho abstraktního, ale naprosto konkrétní koncepty, které pokud zaměníte v kódu, nastane průšvih. Navíc se tu nebavíme o nějakém klábosení ajťáků večer u piva, ale o naučném článku, který by měl být maximálně přesný, protože jinak mate.

              Nejde o konceptuální dogmatizmus, fakt, jestli tomu říkáme, nebo neříkáme třída nemá nic společného s tím, jestli jsou třídy oblíbené, používané, dobře používané… Nikdo se tu nehádá o tom, jestli je prototypování lepší, než třídy, nebo ne.

              Prohlášení o tom, že někdo, kdo je schopný programátor + má publikační činnost patří k jedněm z nejlepších programátorů mě vždy rozesměje. Teď se nechci pana Steigerwalda dotknout osobně, tato výtka se ho netýká, ale pane Nešetřile, znáte VŠECHNY programátory v Čechách, abyste mohl takhle hodnotit? Navíc od kdy se dobrý programátor = dobrý publicista?

              Neinteligentní Neuvažující Člověk

            3. xx

              Re: Špatný článek

              > Místo chápání konceptů se brání definicemi pojmů.

              Tady nikdo neříká, že to má být na úkor chápání konceptů.

              Koncepty se hodí, když o problému přemýšlíte v „obecné rovině“. Ale až vymyslíte, jak se problém dá vyřešit, je potřeba ověřit, že váš postup je správný. A zde už si s koncepty nevystačíte. Zde už potřebujete zadefinovat problém, popsat algoritmus na jeho řešení a dokázat, že řeší definovaný problém.

              1. Aleš Roubíček

                Re: Špatný článek

                Jak souvisí algoritmizace kokrétně s JavaScriptem? V JS jde hlavně o reaktivní proces…

                V JS jsou platné především koncepty.

              2. koroptev

                Re: Špatný článek

                tohle je docela zajimave, co jste nevedomky zminil – algoritmus – tenhle clanek byl o vsem jinem nez o algoritmech, a prijde mi to symptomaticke, zel i pro me vlastni zamestnani ..

      2. Bauglir

        Re: Špatný článek

        Děkuji za reklamu, jsem to já :)

        ad 1/ ano, specifikace mluví o třídách asi na 5 místech… všude, kde vysvětluje, v čem se JS liší od třídních jazyků.

        ad 2/ konsenzus je dohodou/porozuměním mezi lidmi, na faktech ale obvykle nic nemění :). Můžete si tomu říkat třeba druh ovoce ale ovocem se to nestane. JS prostě nemá třídy :)
        Fakt, že tomu Vy a další budete říkat třídy vede jenom k tomu, že se programátoři, kteří k JS přijdou z jazyků, které podporují třídy, budou snažit opakovat stejné postupy, na které jsou zvyklí a oni prostě v JS nepůjdou… Když to řeknu jinak, pokud budu přecházet mezi ObjectPascalem, PHPkem a C#, změním spoustu věcí, syntaxi, knihovny, frameworky… ale nezměním paradigma pro vytváření objektů. Pokud se ale dostanu k JS, tak třídní paradigma musím zahodit a musím začít přemýšlet v prototypech.

        ad 3/ nemám problém přiznat, že s primitivními typy jsem se sekl. Nicméně i Vy máte Vašem rozsáhlém popisu chybu:
        „Převést primitivní hodnotu na její objektovou reprezentaci, lze pomocí přímého volání konstruktoru, ani nemusíme použít new.“
        Samozřejmě musíte, zkuste si pro změnu i Vy nějaké příklady


        var a = Number(2);
        var b = new Number(5);
        a.data = 5;
        b.data = 5;
        alert(a.data + "n" + b.data + "n" + (typeof a) + "n" + (typeof b));

        i specifikace jasně píše: „The Number Constructor Called as a Function: When Number is called as a function rather than as a constructor, it performs a type conversion. Number ( [ value ] ):
        Returns a Number value (not a Number object) computed by ToNumber(value) if value was supplied, else returns +0.“

        4/ nebojte se, já si to pročetl a pročtu si i další díly, některé věci, které jsem ani nekomentoval, protože předpokládám, že budu mít možnost v jiných částech

        1. Daniel SteigerwaldAutor příspěvku

          Re: Špatný článek

          Díky za upozornění, mělo tam být Object místo Number. Ve čtyři ráno už člověk není tak pozorný ;) „When Object is called as a function rather than as a constructor, it performs a type conversion.“

        2. olin

          Re: Špatný článek

          Naprosto souhlasím (jsem také čtenářem ECMA-262). Uvidíme ale až v pokračování seriálu, jestli detailní vnímání specifikace a přesné chápání pojmů bude mít vliv na pochopení souvislostí, protože i nesrovnalosti v pojmech se často řeší dobře zvolenými příklady. A nakonec se stejně lidé vracejí k příkladům, než k textu. Učebnice z tohohle seriálu prostě nebude, informační hodnotu ale mít bude.

  16. MD

    jiny jazyk

    Nechci vypadat jako hnidopich, ale z tehle obsahle diskuse mam cim dal vic pocit, ze javascript je velmi nepovedeny jazyk. Proc se musi objevovat techniky jak udelat tohle a jak tamto, misto toho, aby to bylo zakotveno primo ve specifikaci jazyka? Prijde mi to stejne spatne jako zakony – potrebujete k nim pravni vyklad, abyste vubec vedeli, co se tim zakonem vlastne chtelo rict.

    Nejsem zadny odbornik, ale treba actionscript mi prijde jako mnohem povedenejsi scriptovaci jazyk (klicova slova jako package, class, extends napovi…)

    1. Ondřej Žára

      Re: jiny jazyk

      Možná bych nahradil přívlastek „nepovedený“ za „komplexní“ či „složitý“. S dodatkem, že na první pohled vypadá jednoduše, ale zdání klame.

      Zakotvení některých principů ve specifikaci by situaci jistě svým způsobem usměrenilo, jenže právě nesmírná flexibilita a expresivnost jazyka je jeho hlavním atributem.

      Lehce negativním důsledkem pak je, že jedna „technika“ (v tomto případě OOP) je v praxi realizovatelná několika různými způsoby. Jejich přednosti, ale hlavně nevýhody, pak (doufám) jsou/budou zmíněny v této i dalších kapitolách článku.

      Rozumný čtenář si stejně nakonec vybere sám – za předpokladu, že korektně pochopí všechny principy, bude jeho volba jistě správná.

      1. pr.rybar

        Re: jiny jazyk

        Komplexnost a zlozitost jazyka je zial v pripade Javascriptu a jeho nasadenia dost nevhodna.
        Techniky riesenia mennych priestorov a dedenia su problematicke.
        Myslim, ze napriklad Python by bol ako potencialna nahrada Javascriptu omnoho produktivnejsia a vhodnejsia pre beznych programatorov.

    2. koroptev

      Re: jiny jazyk

      tohle se urcite nebude libit – protoze mozna urceni, duvod existence, ucel JS byl puvodne byt skriptovacim embedded jazykem a to embedded zejmena uvnitr nejakych jiz existujicich datovych struktur (prohlizec – DOM), proto ten duraz na lehkou modifikaci prostredi (prototypovy objektovy system, moznost prilepit si cokoli kamkoli) a mensi na vytvareni rozsahlych veci od nuly (vypusteni modulu, ne tridy)

      a k tomu ucelu ho ohybat potreba asi nijak zvlast neni/nebyla

      no ale lidi delaj vsechno a kdyz tam jsou plne closures, pak lze i toto

      jelikoz se doba posunula a ten ucel se asi trochu posunul, tak ted dle Wikipedie ( http://en.wikipedia.org/wiki/ECMAScript#Features_2 ) jsou asi i ty tridy na poradu dne..

  17. koroptev

    se pridam ke kritice

    1.) javascript (soucasna verzi) je hodne jednoduchy a minimalisticky jazyk, moc konceptu tam neni, proc do nej zavadet pojem „trida“, kdyz OOP system, ktery pouziva, je tzv. prototypovy a „klasicka“ OOP (dejme tomu C++ cesta) terminologie zde nedava smysl?
    2.) scope je velmi jednoduchy koncept, nevynalezl ho javascript a neni na nem nic sloziteho, priklad s mercedesem v garazi se ztmavenymi okny je naproste psycho, asi jako zmrvit vtip a divat se na taktni utrpne usmevy lidi kolem
    3.) closure neni jiny nazev pro scope, tak jak to chapu, je to vec implementace scope, scope rozhodne maji i jazyky, ktere closury s tou funkcionalitou, na kterou jsme zvykli z funkcionalnich jazyku, neimplementuji
    4.) „V Javascriptu platí, že vše co není primitivní typ je asociativní pole, krátce objekt. Funkce je objekt..“ → vyplyva z toho, ze funkce je asociativni pole? a je?

    zbytek jsem necetl, kecy nectu

    1. David Grudl

      Re: se pridam ke kritice

      ad 1) pojem třída už zaveden je a cílem článku je ho vysvětlit. Zkuste spíš zvážit, jestli je C++ skutečně ono „klasické OOP“, nebo spíš jestli neexistuje OOP v podání C++ stejně jako OOP v podání JavaScriptu. C++ je poměrně mladý jazyk, batole proti OOP.

      ad 2) scope JavaScript nevynalezl. Kdo to tvrdí? Proč to vyvracíte?

      ad 4)

      var funkce = function() {
          alert('ahoj');
      }
      
      funkce.a = 1;
      funkce.b = 2;
      
      alert(funkce.b); // vypise 2

      Ehle, je to tak, funkce je asociativní pole. Mýlil jste se, takže článek by pro vás byl velmi užitečný.

      1. koroptev

        Re: se pridam ke kritice

        1.) C++ (popr. jazyky, ze kterych vychazi jeho OOP – a jejich terminologie) je starsi nez JS, „popularizoval“ li se v souvislosti s tim C++ nejaky pojem (trida napr.), je trochu hloupe, kdyz ho nekdo pozdeji ohyba, muj nazor
        2.) narazel jsem na velmi neobratne vysvetleni, na tu nepruhlednou omacku + nektere komentare, ktere z toho delaji neco, co to neni, kdybych napsal „vysvetlovanim toho, co to je scope, objevujete kolo (v pripade, ze to delate neobratne za pomoci mercedesu) a nosite drivi do lesa“ bylo by to srozumitelnejsi“? Konkretne k te posledni otazce (vyvraceni) – protoze chci, prekvapive, vim, zvykejte si.
        4.) nevedel jsem to, pripoustim, ze jsem spis predpokladal opak, ale proto jsem se ptal, abych se to dozvedel; ne ze by to menilo neco na tom, jakym zpusobem JS (nebo funkce v JS) pouzivam (nebo spis nepouzivam, ackoli se mi libi – kvuli neexistujici nativni implementace s nejakou relevantni mnozinou knihoven – neco jako Jscript.NET, pro ktery jsem ovsem nenalezl nejake podpurne nastroje)

        muj hlavni dojem – mel-li to byt clanek o tom, kterak implementovat tridni objektovy system pomoci closures, pak to stacilo napsat, neni v tom vubec nic JS specifickeho, cili se dala vypustit cela ta omacka, mateni (pod pojmem OOP v JS si clovek asi predstavi neco jineho) a neumele vysvetlovani pojmu..

        1. olin

          Re: se pridam ke kritice

          ad 4) Neboj se. Tvrzení, že funkce či objekt je asociativní pole, vystihuje sice na první pohled podstatu, není to ale vůbec přesné. Asociativní pole je totiž pouze datová reprezentace, zatímco objekt a funkce jsou složitější pojmy. Zůstanu proto jen u objektu, což je v JS množina vlastností (hodnot, prototypu, funkcí, konstruktorů…) – slovy OOP by se dalo říct, že obsahuje atributy a metody.

          Říkat, že objekt je asociativní pole, je hodně zjednodušující (i když pro mnohé začátečníky dostačující).

          Např. pro datový typ Array – navzdory tomu, že to je Object – to třeba neplatí, protože operace přiřazení (x[4]=5) nepřiřazuje pouze ke klíči 4 hodnotu 5, ale zároveň upravuje vlastnost (atribut) length.

          Jiný příklad nalezneme hned u další vlastnosti JS – prototypové dědičnosti. Zde také naráží myšlenka asociativního pole, protože se při nenalezení klíče v dané instanci hledá v objektu schovaném pod klíčem prototype (pak případně i v jeho prototype a tak dále, dokud už další prototype neexistuje).

          Na objekty tedy lze s jistou dávkou zjednodušení pohlížet jako na asociativní pole, je to ale velmi chytré (až vyčůrané) asociativní pole :-)

          Tenhle článek obsahuje spoustu takových nepřesností. Nu což, někomu to prostě vadí, někomu ne. Já si myslím, že až bude článek kompletní, tak si v něm každý něco najde. Ten, komu vadí pletení pojmů, se může od pojmů odtrhnout a odnést si jádro věci. No a ostatní se na pojmy zas tak nekoukají, takže si odnesou to samé :-)

      2. pr.rybar

        Re: se pridam ke kritice

        > ad 1) pojem třída už zaveden je a cílem článku je ho vysvětlit.

        Prosim mohli by ste nam predviest ako zapiseme triedu v Javaskripte? Myslim skutocnu triedu/typ a nie prototyp objektu.

        1. koroptev

          Re: se pridam ke kritice

          to samozrejme nejde; tridni OOP lze zavest pomoci closures, jak je ukazano v clanku, coz je o dost pohodlnejsi, nez simulovat OOP v C, coz ale rovnez lze a rovnez to z C nedela objektovy jazyk alespon dle dnesnich obvyklych standardu vnimani tohoto terminu

          1. peter

            Re: se pridam ke kritice

            Kedze neexistuje trieda, nie je ziadne „triedne“. Javascript ma prototypy. Je to prototypovaci objektovy jazyk a nie triedny. Ci si Vy osobne, alebo autor clanku zavediete nejaky pojem a budete ho pouzivat na veci nic nemeni.

            1. Daniel SteigerwaldAutor příspěvku

              Re: se pridam ke kritice

              Docela by mne zajímalo, jaká je Vaše definice třídy. Podělíte se s námi?

                1. Michal Augustýn

                  Re: se pridam ke kritice

                  Nesouhlasím. Specifikace JavaScriptu sice pojem třída nezná, ale proč bychom si ho nemohli zavést? Pojem „třída“ pro JavaScript bych přirovnal v návrhovému vzoru.
                  Jestli má tento „návrhový vzor“ v případě JavaScriptu smysl a je dobré ho používat, to je věc na další diskuzi…

                  1. peter

                    Re: se pridam ke kritice

                    Skuste napisat clanok o 3D grafike a namiesto „vertex“ pouzivat slovo „point“, namiesto „edge“ pouzivat slovo „line“ a namiesto „face“ pouzivat slovo „plane“. Asi vas za odbornika povazovat nebudu hoci ste uz co to v 3D naprogramoval.

                    Pojem „trieda“ je vseobecne znamy, definovany a zauzivany v jazykoch ktore triedy maju. Pretazovat pojem „trieda“ len preto, ze autor clanku nema v slovniku dost slov je nevhodne a nehodne skutocneho odbornika.
                    Alebo sa chcete vy, alebo autor clanku, preslavit ako vynalezca tired v jazyku, ktory triedy nema?
                    Ako vidite vasa originalna trminologia vyvolava iba nepokoj a vlnu nedorozumeni v diskusii.

                    Hovori sa: „Ak pomenujete v jazyku C parametre funkcie main inak ako argc a argv je to urazka vsetkych skutocne dobrych programatorov v jazyku C.“
                    Hovorit o triedach v Javascripte je nieco podobne. :(

                    1. Daniel SteigerwaldAutor příspěvku

                      Re: se pridam ke kritice

                      Tak už sem konečně hodně tu vaši správnou definici pojmu třída, ze které bude zřejmé, že Javascript třídy nemá. Nedáte-li ji sem, pak jste jenom otravný troll.

                      1. paranoiq

                        Re: se pridam ke kritice

                        Dane, nejsem žádný OOP expert. mé objektové vzdělání je omezeno pouze na C++, PHP, Python a Javu. pokud ale z těchto čtyř vyvodím nějakou definici třídy (a nechtěj prosím abych ji psal), dojdu k závěru, že JS třídy nemá (někde uvnitř hlavy mám dvě množiny „třídní OOP“ a „prototypové OOP“. nemají průnik)

                        pozor, to nám ale nijak nebrání třídy v JS používat! :P

                        když jsem kdysi poprvé zkoumal možnosti třídního OOP v JS narazij jsem na myšlenku, že třídní vlastnosti mohou být pomocí jiných prvků jazyka ‚emulovány‘. s takovou definicí jsem osobně naprosto spokojený

                        velice ti děkuji za článek a těším se na příští

                        1. belzebub

                          Re: se pridam ke kritice

                          Mozna je na case naucit se nejaky JINY jazyk :)

                          Vase argumentace je podobna tvrzeni: „Jezdil jsem uz ve Felicii, ve Fabii i v Oktavce, a vsechny mely masku chladice v podobe svislych mrizek. Proto musi byt maska chladice vzdy ze svislych mrizek“.

                    2. Michal Augustýn

                      Re: se pridam ke kritice

                      Ale tady to asi někdo vůbec nepochopil! Šup šup, přečíst můj „názor“ ještě jednou ;-)
                      Já neříkám, že by se mělo místo zavedených pojmů používat něco jiného. Já říkám, že může být vhodné zavést označení pro nějakou typickou konstrukci, de facto tedy pojmenovat návrhový vzor.

                      V některých jazycích prostě třídy jsou v základní syntaxi (např. C#), v některých ne (např. JavaScript) a tudíž může být vhodné si to tam nějak dobastlit.

                      Je to podobné, jako by tu byl třeba článek „Implementace singletonu v C#“ a Vy jste tu vykřikoval, že ve specifikaci C# žádný singleton není a tudíž je úlná blbost o něčem takovém psát, že to přináší jen zmatení a že přece hlavní metoda programu by se měla jmenovat Main.

                      Btw. jestli jste mě chtěl oslnit svými znalostmi z počítačové grafiky, bohužel Vás musím zklamat. Vývoji herních, potažmo grafických enginů, jsem se věnoval intenzivně několik let, obhájil jsem na podobné téma diplomovou práci a i si střihnul nějakou tu přednášku na konferenci pro herní vývojáře ;-)

                2. Daniel SteigerwaldAutor příspěvku

                  Re: se pridam ke kritice

                  Nečetl jste text pozorně, ve své otázce sem se neptal na definici Javascriptové třídy. Ptal sem se, na definici třídy jako takové. Jelikož zcela přesně víte, co třída není, podělte se prosím o vaši definici.

  18. junix

    OOP, dedicnost

    Podlehl jsem stejnemu pocitu, jako vetsina diskutujicich, ze vsemu rozumim nejvice :) a mam potrebu se vyjadrit jak k clanku, tak k diskusi.

    1. K diskusi – vede se tu plamenna debata o tom, jestli ma javascript tridy, o nejakem „klasickem OOP“ a „prototypickem OOP“ a ze jedno ma polymorfismus a druhe ne a podobne nesmysly.

    OOP je jedno. Jedna se o obecny pristup, ne o konkretni podobu v nejakem jazyce. Vychazi predevsim ze dvou veci: objektu a jejich chovani – polymorfismu. Nic vic.
    Pak jsou tu dva sekundarni principy – zapouzdreni, a dedicnost.
    U dedicnosti vidime rozdily, ktere tu zatim nikdo spravne nepojmenoval.

    Mame tu tridne-instancni dedicnost (C++, Java, Ruby, Python, SmallTalk, CLISP atd.), kde je dedicnost staticka, definovana mezi tridami. Objekty jsou pouze instance. To je mimochodem princip velmi vzdaleny realite, ale jednoduseji realizovatelny.

    Druhy typ je dedicnost prototypicka (self, IO), ktera je dana primo vztahy mezi objekty. Objekt A je potomek objektu B, protoze B je jeho prototyp. To je urcite neco blizsiho realite.

    Ano, dedime nektere rysy lidskeho druhu, ktery je zdedil z opice (tridne-instancni pripad). Spis ale dedime konkretni rysy a vlastnosti od nasich rodicu, kteri je zdedili od svych a az nekde hloub byl nejaky predek konkretni opice atd (prototypicky pripad).

    Ve skutecnosti jsou tyto dva pripady pouze hranicni body, a konkretni implementace dedicnosti v ruznych jazycich je posunuta k tedne, nebo druhe strane:

    C++: Ciste tridne-instancni, tridy jsou pouze definice, pracuje s nimi pouze kompilator, nejsou to objekty.
    Instance nejsou vytvareny tridami, ale specialni konstrukci jazyka – operatorem new.

    Java: Uz je o krucek jinde. Tridy maji sve zapouzdrujici objekty, umoznujici s nimi „nejak“ pracovat za behu.
    Objekty jsou stale vytvareny operatorem new

    SmallTalk, Ruby: Tridy uz jsou plnohodnotne objekty. Vytvareji sve instance svymi metodami a ne zadnym spec. operatorem.

    JavaScript: Je bliz protoypicke dedicnosti, ale neni to uplna PD. Proc? Protoze prototyp neprirazujeme objektu, ale jeho konstruktoru.

    IO, Self: Ciste prototypicka dedicnost – objekty se vytvareji klonovanim existujicich objektu a pridavani dalsich vlastnosti.
    Klonovanim vznikne objekt pouze s referenci na prototyp. Nove vlastnosti se ukladaji do nej.

    Kdyz se tedy vratim k tomuto problemu v JavaScriptu, tak je videt, ze je napul cesty. Neni ani tridne-instancni, ani striktne prototypicky (prestoze se tak vetsinou oznacuje).
    Kdyz v JS vytvarime novy objekt, neni to „z jineho objektu“ ale „nejakym zpusobem“, pomoci funkce oznacene jako konstruktor. Tento princip je stale blizsi tridne-instancnimu modelu a tudiz neni nijak zavadejici, pouzivat pro funkci, kterou pouzivam jako „vytvarejici“, oznaceni Trida. Je to naopak vhodnejsi, nez mast ctenare hned komplikovanou prototypickou dedicnosti, ktera stejne nektere prvky te tridne-instancni obsahuje.

    I v ostatnich vecech, ktere jsou clanku vytykany, se vetsinou jedna o omyly. Snad byly vsechny vyjasneny ostatnimi prispevateli.

    Osobne si myslim, ze to, co bylo predmetem tohoto dilu clanku, bylo vysvetelno dobre. Jestli je clanek spravne usporadan, to asi kazdy vnima jinak. Myslim, ze pokud ho docte cely, tak uz mu porozumi, a urcite bude lepsi uceleny dojem, az vyjdou i ostatni dily.

    Co bych vytkl ja, je krome drobnosti (to je spis doplneni), ze ve scopu najdete i parametry nadrazene funkce (cili zavadeni lokalni promenne, do ktere se tyto ukladaji, je zbytecne a da se pracovat s parametry name primo), predevsim hodnoceni, ze nektere pristupy jsou spatne a nektere dobre.

    V teto diskuzi jsou vsichni odbornici provereni praxi, a tak se i ja budu ohanet tou svou :), ve ktere jsem se uz setkal
    s nescetne situacemi, kdy byly vyhodne ruzne pristupy k reseni
    dedicnosti. At uz vytvareni vzdy novych objektu, jako je to v prvnim spatnem prikladu – mimochodem pokud chcete rozsirovat nektere built-in objekty prenositelne, tak se tomu nevyhnete, tak jsem casto vyuzil uzavery a metody jako jejich rozhrani.

    Je to otazka konkretni situace a ne, ze jedno je spatne, a druhe dobre (resp. treti, co bude prezentovano priste).

    Na dalsi dily se urcite tesim a i tento prvni hodnotim kladne.

    1. Daniel SteigerwaldAutor příspěvku

      Re: OOP, dedicnost

      Díky ze vynikající a zevrubný komentář. Jak prototypová dědičnost v Javascriptu přesně funguje, tomu se budu věnovat v druhém článku. A myslím, že vypíchnu jednu charakteristiku, která je naprosto zásadní, ale jenom málokdo si ji uvědomuje.

      S tím zdvojením name a p_name máte samozřejmě pravdu, name není nutné. Zde však slouží jako ilustrace, protože v „tom správném“ příkladě (který bude v druhém díle), se lokální name stane instanční vlastností ( this.name = name).

      K hodnocení že tyto techniky jsou špatné, mělo asi zaznít (velkými písmeny a červeně ;), že jsou špatné pro tvorbu tříd. Ještě přesněji, „zneužití closure“ má význam pouze pro funkcionální programování, v nějakém algoritmu, nebo tam kde potřebuji callback. I v takových případech pak ale nehovoříme o tvorbě tříd. Co se týká techniky druhé, vytváření metod v konstruktoru. Tato technika je dle mého špatná vždy. Respektive nevybavuji si jediné její oprávněné použití. Ale rád se nechám poučit, pokud o nějakém takovém využití víte, sem s ním.

      Co se týká dědění vestavěných objektů, které máte na mysli? Funkci podědit nelze. Pole ano, ale nebude správně fungovat v Internet Exploreru. Čísla, řetězce, ani booleany jsem dědit nikdy nezkoušel.

      1. junix

        Re: OOP, dedicnost

        Pokud trida je takova funkce, kterou pouzivame pri vytvareni objektu pomoci operatoru ‚new‘, pak prvni zpusob nejenze je spatne, ale ani nelze pouzit. To mate pravdu.
        Na druhou stranu vytvareni objektu pomoci ‚new‘ neni jediny univerzalni zpusob. Kuprikladu DOM objekty muzete vytvaret pouze pomoci funkci, takze pro vytvoreni konkretniho DOM objektu (napr. DIV element s konkretni css tridou a id) budete muset vytvaret necim podobnym, jako je ten prvni priklad.

        Druhy priklad se s vyhodou pouzije nejen u callbacku, ale rozhodne pri elegantnim reseni navrhoveho vzoru state, cili implementaci stavoveho polymorfismu.

        Rozhodne se mi libi, ze v JS muzete mit stavovy polymorfismus nejen pro konkretni objekt, ale pro celou „tridu“. Ale to uz nesouvisi s uvednymi priklady.

        1. v6ak

          Re: OOP, dedicnost

          No rozhodně není nutné, abych instanci vytvářel přes new. Existuje tu Factory, což umožňuje některé zajímavé věci v přesunu zodpovědnosti.

        2. Daniel SteigerwaldAutor příspěvku

          Re: OOP, dedicnost

          První odstavec, souhlas (o DOM elementech ale nebyla řeč, to je jaksi mimo Javascript).

          Druhý odstavec, chci vidět kód, stačí ilustrativní. Myslím totiž, že nemáte pravdu. Neznám pattern, jehož implementace by vyžadovala vytváření method v konstruktoru (o tom by druhý špatný příklad). Možná se pletu, ale bez ukázky kódu se nepohneme dál.

          Třetí odstavec. Přesouhlasím, viz. druhý díl.

      2. aprilchild

        Re: OOP, dedicnost

        muzes Dane prosim rozvest, „zneuziti closure“ pro funkcionalni programovani? Resp. uvest nejaky priklad? Mam na mysli ciste funkcionalni priklad, bojim se, ze pouziti closure jde presne proti jeho duchu, zaklinadlem budiz immutable state a no side effects. Neni mi jasne, k cemu bych v cistem navrhu potreboval videl do scope o uroven vys. Ale to je jen spis takova perlicka na zaver – pro puristy:).

        1. Timy

          Re: OOP, dedicnost

          Co třeba toto? Je to v Lispu, ale mělo by to být srozumitelné (násobí to všechny prvky seznamu coef), mapcar dělá prakticky totéž co array.each v MooTools nebo jQuery.

          (defun multiply (coef list)
                  (mapcar (lambda(x)
                             (* x coef))
                     list))
          
          > (multiply 2 '(1 2 3 4))
          (2 4 6 8)

          Do toho mapcaru (each) posílám anonymní funkci, která musí vidět o scope výše, aby se dostala ke  coef.

        2. Daniel SteigerwaldAutor příspěvku

          Re: OOP, dedicnost

          Nepovažuji se za odborníka na funkcionální programování, ale mám pocit, že koncept closure se nijak nebije s immutable state. Ani Tomáš Petříček to ve své knize nikde nezmiňuje.

          8.2.2 Capturing state using closures in F#
          In this section we’re going to talk about closures, which is an important concept in functional programming. Closures are very common and most of the time they aren’t used with mutable state. However, working with mutable state is sometimes needed for the sake of pragmatism and closures give us an excellent way to limit the scope of the mutable state.

          (Functional Programming for the Real World)

          Docela mě potěšilo, že Tomáš zmiňuje vlastně to samé, co jsem zmiňoval v úvodu svého seriálu. OOP a funkcionální programování nejdou proti sobě. Kdy je tedy správné použít closure? Prostě kdykoliv se mi hodí, aby funkce viděla do scope vyšší úrovně. Dejme tomu, že máme funkci, která využívá jQuery. To, že funkce vidí jQuery z globálního scope je přeci úplně intuitivní, ne? Dále, funkce pracuje s nějakými daty, které jsou definované vně funkce. To, že na ně vidí, je opět velmi praktické. Ale ty chceš příklady, ne kecy, rozumím :)
          Tak třeba ten each, přepsaný do Javascriptu:

          var multiply = function(number, array) {
              return array.map(function(item) {
                  return item * number; // na number je nutné vidět :)
              });
          };
          alert(multiply(2, [1, 2, 3, 4])); 

          Lze si představit mnoho obměn, typicky array.sort třeba. Další příklady jsou variantou techniky známé jako currying. V javascriptu ji používáme hodně, tak často, že si to už ani uvědomujeme ;) Většina příkladů na webu jsou totiž podivně nepraktické příklady typu: chci mít funkci, která mi vytvoří funkci, která bude přičítat nějaké číslo. Třeba takto:

          var makeAddFn = function(number) {
              return function(value) {
                  return value + number;
              };
          };
          var add2 = makeAddFn(2);
          alert(add2(1)); 

          K čemu je takový zápis dobrý? K ničemu! ;) Skládat algoritmus z předpřipravených generovaných funkcí je (až na výjimky) cesta do pekla. Tohle je práce pro třídy, dědičnost, agregaci atd.

          Nutnost, nebo spíše krásu closure si uvědomíme v okamžiku, kdy píšeme asynchronní kód. Typicky volání serveru, animace, opožděné zobrazení něčeho atd.. díky closure můžeme provázat vyvolání akce s asynchronním obsloužením výsledku, aniž bychom museli vytvářet nějakou novou datovou strukturu, do které bychom vazbu explicitně ukládali.

          var save = function(id, data) {
              server.call('user.save', data, function() {
                  User.lookUp(id).update(data);
              });
          }; 

          Díky closure si nemusíme ukládat id někde bokem, případně si jej vracet ze serveru.

          1. aprilchild

            Re: OOP, dedicnost

            Diky, vicemene se tvuj (a ostatnich) pragmatismus ohledne closures shoduje s mym nazorem, byt treba v Erlangu bys asi brzy narazil (ne kazdy jazyk je tak ohebna bestie jako JavaScript). Closure pro mutable state je nicmene vytvareni side effects a „ciste“ funkcionalni programovani to neni. Ale za definice nikdo hlavy utinat nebude. Pragmatismus necht (z)vitezi..;).

              1. aprilchild

                Re: OOP, dedicnost

                Pokud pomoci closure ctu neco v odlisnem scope, side effect nevznika (splnena podminka nemennosti). V pripade, ze stav menit budu (kdybych napr. o uroven vys zvysoval counter apod.), side effect vytvarim a purista by o mem kodu rekl, ze neni funkcionalni. Jsou jazyky, kde jsem tohoto pokuseni usetren (promenne jsou automaticky immutable), v nekterych (js) to mozne je (a v nekterych si restrikce urcuju sam – Scala).

                Nekdy se to „necista“ praktika zasahu do stavu jineho scope muze hodit – pokud znam dusledky takoveho pouziti, ale obecne je lepsi se ji vyhybat (lze ji vicemene bezpecne pouzit jen tehdy, kdy jsem si jist, ze dany kod pobezi ‚synchronized‘ pouze v jednom procesu v jeden cas).

                Ale to uz je debata o necem jinem, diskuzni vlakno vzniklo jen jako reakce na pouziti closures ve funkcionalnim programovani, ktere Dan zminil.

  19. hon2a

    Dekuji za velmi kvalitni clanek

    Rad bych pripojil tento komentar jako protest ci protivahu vetsinou zjevne nepromyslenych nebo argumenty nepodlozenych komentaru uvedenych vyse. Precetl jsem vsechny tri dily serialu a reaguji tedy na serial jako celek.

    Vase clanky splnily (a predcily) ma ocekavani a pomohly mi vyjasnit si nektere aspekty implementace „tridni“ dedicnosti v JavaScriptu. Nesouhlasim s vyse uvedenym nazorem, ze rozdeleni prvnich dvou dilu je nevhodne. Prave naopak si myslim, ze rozdeleni je prinosne i z jinych nez technickych duvodu, nebot dava ctenarum prostor, aby se sami pokusili zamyslet nad korektnim resenim problemu.

    Naprosto nesouhlasim s opakovanou „kritikou“ Jiriho Hrebenare a dalsich, zpusobenou bud prilis zbeznym prectenim clanku nebo dokonce nepochopenim prave tech principu, jejich nepochopeni tak radi vytykaji Vam, a zalozenou na velmi zmatene argumentaci. Pokud bych po precteni clanku pochyboval o jeho dobre strukturovanosti a vyborne pochopitelnem stylu, staci pro rozptyleni pochyb porovnat Vase clanky s jim uvedenymi odkazy.

    Jeste jednou dekuji a preji hodne inspirace pri dalsi tvorbe.

  20. brouk

    nechápu tvrzení, že #nefunguje operátor instanceof

    V té části 2.5.2 „Vylepšené“ třídy nechápu tvrzení, že #nefunguje operátor instanceof,
    Animal je typ a proměnná kitty je instancí tohoto typu, tudíž alert(kitty instanceof Animal); vrácí správně true. Jak říkáš, že closure a privilegované metody se pro každou instanci vytváří zas a znova, což je nemalá (a hlavně zbytečná) zátěž, tak níže uvedený zápis je zcela ekvivalentní tvému prototypování, kde uvádíš důkaz, že metody jsou sdílené:
    var Animal = function(p_name) {
    this.name = p_name;
    this.showName = function() {
    alert(name);
    }
    };
    var mici = new Animal(‚Mici‘);
    var kevi = new Animal(‚Kevi‘);
    alert((mici.getName === kevi.getName)); // true
    alert((mici.getName === Animal.prototy­pe.getName)); // true
    Zajímavé jsou možnosti HTML5:http://www.adobe.com/devnet/html5/articles/javascript-object-creation.html

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=3191