Autor Zpráva
Kcko
Profil
Ahoj,

dá se nějak rozumně dostat k objektu v privátní metodě? Obě možnosti, co jsou zakomentované mi přijdou nehezké.
Další možností je předávat si context jako argument, ale to je taky nic moc.

Lze to nějak čitelněji, nebo tak jak se to má dělat?

            function Test()
            {
                function _insert()
                {
                
                    console.log(this);
                    $("#a").html(this.text);
                    
                }

                this.text = 'Pokusný text';
                this.run = function()
                {
                    //$.proxy(_insert, this)();  funguje kdyz mame jQuery
                    //_insert.call(this); funguje normalne
                    
                }
            }

            var test = new Test();
            test.run();


Ještě mě napadlo toto tedy:



            function Test()
            {
                var self = this;

                function _insert()
                {
                
                    //console.log(this);
                    $("#a").html(self.text);
                    
                }

                this.text = 'Pokusný text';
                this.run = function()
                {
                    _insert();
                    //$.proxy(_insert, this)();  funguje kdyz mame jQuery
                    //_insert.call(this); funguje normalne
                    
                }
            }
Radek9
Profil
Kcko:
_insert.call(this)
Tohle je poměrně validní způsob. V tu chvíli je ale zbytečné definovat tu funkci uvnitř konstruktoru. Klidně může být sdílená pro všechny instance.

var self = this;
Tohle je preferovaný způsob. Další (podobnou) možností je použít arrow funkci, která si hodnotu this zachovává automaticky:

const _insert = () => {
  $("#a").html(this.text)
}

Případně ještě bind:

const _insert = (function () {
  $("#a").html(this.text)
}).bind(this)

Jinak, je opravdu nutné, aby byla privátní?
Kcko
Profil
Radek9:
V tu chvíli je ale zbytečné definovat tu funkci uvnitř konstruktoru. Klidně může být sdílená pro všechny instance
Jak by měla být sdílená? Ukázka prosím?

ES5/6 způsoby jsou pro mě nečitelné, přesto jsem se o nich rád dozvěděl.

Jinak, je opravdu nutné, aby byla privátní?
Mno ano, tohle je pseudokód, ale nechci mít objekt plný veřejných metod (budou tam obslužné metody a ty se budou volat jen uvnitř, proto je chci privátní), v podstatě to chci mít jako PHP objekt.

Jen si s tím hraji a zkouším co a jak, určité patterny jsem si už našel
Radek9
Profil
Kcko:
Jak by měla být sdílená? Ukázka prosím?
Nějak takhle. Ideálně ještě run navázat na prototyp:
function _insert() {
  console.log(this);
  $("#a").html(this.text);
}

function Test() {
  this.text = 'Pokusný text';
}

Test.prototype.run = function(){
  _insert.call(this);
}

Pokud tu funkci nevyexportuješ ven z modulu, tak se k ní nikdo nedostane.

ES5/6 způsoby jsou pro mě nečitelné, přesto jsem se o nich rád dozvěděl.
A přitom by sis velice ulehčil život. Ať už to jsou ty arrow funkce nebo třídy. Holt to jen pro řadu věcí (pokud je chceš rozjet i ve starších prohlížečích) vyžaduje použití transpileru (Babel, TypeScript apod.).

nechci mít objekt plný veřejných metod
Tomu rozumím, ale vě většině případů je to prostě taková programátorská paranoia. Hrozí reálně to, že by tu metodu někdo zavolal a něco tím rozbil, pokud bude v dokumentaci uvedena jako privátní? Např. TypeScript to dělá tak, že jsou při kompilaci tyto metody označeny jako privátní (tzn. pokud se je pokusíš odněkud zavolat, vyhodí to chybu), ale po kompilaci jsou to úplně normální metody navázané na prototyp.
Kcko
Profil
Radek9,
Díky za ukázku.

V čem je to připojení přes prototypování lepší? Než když to budu mít uvedeno ve funkci, resp objektu , resp dle Tebe v konstruktoru?
Rychlost nebo co?

Líbí se mi více když je to vše hezky u sebe (čili literální objekt nebo funkce => objek). Tohle rozpojení, cos naznačil, se mi moc nelíbí (ne vyložene prototyp, ale spíš ta privátní funkce si tak plave mimo ...).

Tím modulem myslíš uzavření toho všeho souvisejícího do nějakého var myApp = {} nebo do nějakého closure?

Add ES5/6; ano jak říkáš, pořád tam je nepodpora 9/10 snad i IE 11. Vím, že se to dá překompilovat přes nějaký preprocesor, ale já nejsem hard vývojář JS :), na tohle celé se ptám spíš se zvědavosti a taky proto, že když píši nějaký obslužný JS na frontend, tak chci aby to trošku vypadalo a bylo to znovu použitelné.


Na ukázku, není to nic extra, ale přijde mi to lepší, než to flákat spageti kódem.
Takže se ještě zeptám, je na tom něco extra špatně? A proč tedy prototypovat? Na to se ptám i tedy v předchozí otázce.
Pokud se Ti chce ještě reagovat, tak prosím :-)

    function Calendar(el)
    {
        
        this.el     = $(el);
        this.header = $('thead', this.el);
        this.body   = $('tbody', this.el);
 
        this.open = function() {
            this.el.removeClass().addClass('open calendar');
            this.showBody();
        };        
        this.close = function() {
            this.el.removeClass().addClass('calendar');
            this.hideBody();
        };
 
        this.showBody = function() {
            this.body.show();
        };
 
        this.hideBody = function() {
            this.body.hide();
        };
 
        this.toggle = function() {
 
            this.body.is(':visible') ? this.close() : this.open();
 
        };
 
        this.selectDate = function(date) {
            this.header.find('th').text(date);
        };
    }
    
    
    // usage
    
     var calendar = new Calendar('#calendar');
 
     calendar.header.click(function(){
            calendar.toggle();
     });     
 
     calendar.body.find('td.num').click(function(){
            calendar.selectDate($(this).data('date'));
     });
    



var hamburger = {
 
        init: function(el) {
            this.elements             = {};
            this.elements.el          =  $(el);
            this.elements.header      =  $('#header-mobile');
            this.elements.closeButton =  $('.hamburger-close');
        },
 
        open: function(e) {
            this.elements.header.fadeIn();
            e.preventDefault();
        },
 
        close: function(e) {
            this.elements.header.fadeOut();
            e.preventDefault();
        },
 
        getElement: function(el)
        {
            return this.elements[el];
        }
    };
 
 
    // init
    hamburger.init('.hamburger');
 
    // open
    hamburger.getElement('el').click(function(e){
        hamburger.open(e);
        $('#bg-overlay').show();
        
    });
 
    // close
    hamburger.getElement('closeButton').click(function(e){
        hamburger.close(e);
        $('#bg-overlay').hide();
    });
Radek9
Profil
Kcko:
V čem je to připojení přes prototypování lepší? Než když to budu mít uvedeno ve funkci, resp objektu , resp dle Tebe v konstruktoru?
Ta metoda je potom sdílená pro všechny instance. Tvoje řešení vytváří pro každou instanci zcela novou metodu, což je paměťově i výkonově neefektivní. Záleží, kolik těch instancí bude.

Tohle rozpojení, cos naznačil, se mi moc nelíbí (ne vyložene prototyp, ale spíš ta privátní funkce si tak plave mimo ...).
Pro podobné funkce se tohle rozpojení úplně běžně používá. Je to holt na tobě. Ale jak jsem psal výše, vytvářet novou funkci pro každou instanci je neefektivní.

Tím modulem myslíš uzavření toho všeho souvisejícího do nějakého var myApp = {} nebo do nějakého closure?
Pokud to děláš čistě bez jakéhokoli transpileru nebo bundleru, tak prostě pomocí closure:
var Test = (function () {
  function _insert() {
    console.log(this);
    $("#a").html(this.text);
  }
   
  function Test() {
    this.text = 'Pokusný text';
  }
   
  Test.prototype.run = function () {
    _insert.call(this);
  };
  
  return Test;
})();
Kcko
Profil
Díky, natolik JS neznám, abych si to uvědomil. To co jsi řekl dává smysl. Co se týká těch instancí, nejsou to desítky ani stovky, takže je to asi taky v pohodě, nicméně, jsem rád, že jsem se dozveděl něco nového.

PS. JS je oproti PHP trošku divný ;-)
Radek9
Profil
Kcko:
PS. JS je oproti PHP trošku divný ;-)
Není, když píšeš v JS dnešní doby (tedy v ECMAScriptu 2017). U PHP taky přece nepoužiješ 9 let (při srovnání s ES 3 dokonce 19 let) starou verzi. Ten jazyk se nějak vyvíjí a je samozřejmé, že tam přibývají funkce, které programátorům ulehčují život. Např. to, cos popsal, by se krásně i s enkapsulací té privátní metody dalo napsat takhle:

test.js
import * as $ from 'jquery'

const insert = Symbol()

export default class Test {
  constructor() {
    this.text = 'Pokusný text'
  }
  
  [insert]() {
    console.log(this)
    $('#a').html(this.text)
  }
  
  run() {
    this[insert]()
  }
}

něco.js
import Test from './test'

const t = new Test()
t.run()

K insertu se v tu chvíli (pokud tedy nepoužiješ funkce Object.getPrototypeOf a Object.getOwnPropertySymbols) nedostaneš. Podobně (pomocí reflektování) se ale můžeš dostat k privátním metodám i v jiných jazycích.
Kcko
Profil
„PS. JS je oproti PHP trošku divný ;-)“ 
Není, když píšeš v JS dnešní doby (tedy v ECMAScriptu 2017). U PHP taky přece nepoužiješ 9 let (při srovnání s ES 3 dokonce 19 let) starou verzi. 

Použiji, na mém hostingu je ještě 5.3ka ;) (není stará 9 let, ale cca 7). CHci tím jen říct, že už v té době měly / mají třídy zapoudřené metody a rozlišenou viditelnost public/private/protected.

Takže, takováhle nepěknost s prototypováním, closurama, vyhazovaním věcí mimo konstruktor atd kvůli neefektivitě v PHP prostě není a to se mi na JS nelíbí.

Nejsem JS vývojář a ukázku cos poslal je pro mě absolutně nečitelná, možná za nějakou dobu.

Přesto díky za výživný topic.
Radek9
Profil
Kcko:
Použiji, na mém hostingu je ještě 5.3ka ;)
V tom případě doporučuji změnit hosting. ;-)

Chci tím jen říct, že už v té době měly / mají třídy zapoudřené metody a rozlišenou viditelnost public/private/protected.
takováhle nepěknost s prototypováním, closurama, vyhazovaním věcí mimo konstruktor atd kvůli neefektivitě v PHP prostě není a to se mi na JS nelíbí.
To je ale proto, že JS není „třídní“ jazyk. Jeho objektový model je postaven právě na té prototypové dědičnosti. Člověk si na to musí nejdřív zvyknout a pochopit to. Mermomocí tam cpát objektové návrhy z jiných jazyků je špatně. Koneckonců to, co jsem napsal v [#8], je vlastně jen sytnaktický cukr na těmi prototypy.
Kcko
Profil
Radek9:
:-)
Nebudu měnit hosting, když nemusím nic platit, navíc jsem v té firmě zaměstnaný (máme i server s PHP 5.6 a nově se 7čkou), narážel jsem hlavně na to co popisuješ v dalším odstavci.

Je to o tom, jak moc je PHP a JS rozdílné a já jsem PHP vývojář (mimo jiné). I když je fakt, že mě ted JS začíná bavit víc (pokukuji po Reactu).
A zpětně mě mrzí, že jsem prodal tuto knihu cdn.albatrosmedia.cz/Images/Product/8486895?3D2F81428EF4B90FA66C2928F9CBAEBE&size=normal-6 aniž bych ji pořádně pročetl (pak bych asi nezakládal ani tento topic).


PS. Rozširuji si GIST o 4 způsob a jsem spokojen :)
Radek9
Profil
Kcko:
A zpětně mě mrzí, že jsem prodal tuto knihu
Tu neznám. Ale osobně (pokud nemáš problém s angličtinou) mohu doporučit Eloquent JavaScript. Je dostupná zdarma online: eloquentjavascript.net
Kcko
Profil
Radek9:
Ale osobně (pokud nemáš problém s angličtinou)
Na úrovni čtení nemám.

Někdy je lepší plácnout se někam na zahradu do klidu mimo telefon / počítač a další lidi a v klidu si číst, než furt civět do kompu, ale díky link ukládám.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: