[JS] volanie vo vhodnom scope

Webdesign, HTML, CSS, Flash, PHP, ASP, .NET, JavaScript. Kritika www stránek na Smetišti.

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod gandor 26. 7. 2010 14:47

Zdravim.
Mam tu taky docela tazsie vysvetlitelny problem, tak sa to skusim opisat 2x. Dufam ze ma niekto pochopi.

Pokus o vysvetlenie 1:
Mam objekt 1, ktory chcem pouzivat podobne ako sa v PHP pouziva trieda (sluzi teda iba ako sablona). V nej mam premennu a metodu.
Z tohoto chcem spravit instanciu tym, ze vytvorim nieco ako
Kód: Vybrat vše
var mojaInstancia=new mojaTrieda()
s tym, ze sa v konstruktore do mojej instancie nejak naplni na nejaku konkretnu hodnotu, ktoru si to bude pamatat...
No a teraz nastava problem v tom, ze potrebujem pustit funkciu z mojaInstancia v dalsiej triede, ale tato funkcia si pyta jej clensku premennu, ktoru samozrejme nemoze dostat...

Pokus o vysvetlenie 2:
Pouzivam funkciu addEvent od Deana Edwardsa a potrebujem jej dat ako spustenej funkcii nieco take, aby to pochopilo, ze chcem spustit z konkretneho objektu nejaku konkretnu funkciu...
V reali sa to podoba na nieco podobne, ako ked sa pouziva
Kód: Vybrat vše
var x=setTimeout('objekt.funkcia',cas);
len netreba pouzivat uvodzovky (predava sa typ funkcia nie string) a s tym, ze to x sa vam nijako nepodari napchat do objektu....

PS. ak sa najde nejaky dobrak, ktory to nejak vyspekuluje pomocou call,apply alebo eval, (alebo v najhorsiom je prijatelna aj funkcia ktorej odovzdam scope, samotnu funkciu a argumenty) tak mu budem velmi povdacny. V kazdom pripade potrebujem to spravit co najcistejsie, preto rady typu nepouzi objekt a sprav to v obore window su mi na 2 veci...

Za kazdu radu vopred velmi dakujem...

EDIT: znamy mi uz nasiel plne funcne, ale "skarede" riesenie. Je to nieco v zmysle
Kód: Vybrat vše
with(mojaInstancia)
{
  taDalsiaTrieda(function(){mojaInstancia.volanaFunkcia();});
}
Ak niekto pride na to ako spravit toto iste cistejsie, tak mu budem povdacny :)
gandor
Mírně pokročilý

Odeslat příspěvekod eskjuell 26. 7. 2010 16:21

přiznám se že úplně nerozumím těm pokusům o vysvětlení :-D , ale napadlo mě, že chceš dostat tohle:
Kód: Vybrat vše
var eventSetter = {
    addHandler : function(element, type, handler)
        {
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent){
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    },
    removeHandler : function(element, type, handler)
        {
        if (element.removeListener) {
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent){
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null;
        }
    }
};



Používá se:
Kód: Vybrat vše
eventSetter.addHandler(window, "load",_load);


Apak funkce:
Kód: Vybrat vše
var _load = function(){
...
}

Snad to k něčemu bude ;-)
hmm..., koblížky
eskjuell
Junior
Uživatelský avatar

Odeslat příspěvekod gandor 26. 7. 2010 17:03

Nepochopil si ma, ale aj tak sme blizsie...
Presne to co si ty dal, ze _load je u mna nieco v zmisle objekt.funkcia.
Pre pochopenie ukazem ako priblizne vyzera u mna ten objekt:
Kód: Vybrat vše
function Navigation(image)
{
   this.image=image;
   Navigation.prototype.moveLeft=function()
   {
      .....
      this.image.style.......
      .....
   }
}

Z tohoto objektu nasledne robim instanciu priblizne takto:
Kód: Vybrat vše
var navigation=new Navigation(document.getElementById('mainImage'));

A problem je v tom, ze ked dam len eventSetter.addHandler(window, "load",navigation.moveLeft);
tak this.image sa referencuje ako eventSetter.image co je samozrejme NULL...
Ja chcem dosiahnut to, aby this.image bolo totozne s navigation.image ALE NIE z Navigation.image.....
gandor
Mírně pokročilý

Odeslat příspěvekod eskjuell 26. 7. 2010 20:48

Asi jak do toho nevidím tak ani nevím jak si to představit.
třeba tady voláš podle ID
Kód: Vybrat vše
var navigation=new Navigation(document.getElementById('mainImage'));

tak to by šlo použít:
Kód: Vybrat vše
eventSetter.addHandler(getElementById('mainImage'), "click",_nejakaFce);

Ale tohle teda asi není ono. Ještě mě napadlo když děláš nějakou instanci tak jí dáš jméno tak tam vytvořit prvek s ID stejným jako jméno. Pak přidáš i eventSetter.
A jestli potřebuješ jinou funkcionalitu eventSetter tak si to tam můžeš připsat a použít to třeba takto:
Kód: Vybrat vše
eventSetter.moveLeft(window, "click",_nejakaFce);
hmm..., koblížky
eskjuell
Junior
Uživatelský avatar

Odeslat příspěvekod gandor 26. 7. 2010 21:14

Nie nie stale sa nerozumieme...

Mame 3 objekty.
1, Objekt s eventami, ktory robi attchEvent a podobne. Ten ma svoj scope pod nazvom eventSetter. No a tento objekt prijima pri volani addEvent funkciu, ktoru v sebe vykonava... ON ALE BERIE FUNKCIU! Teda nie objekt a informaciu ktoru funkciu toho objektu ma pustit. (Z toho vyplyva, ze ked prijime funkciu X(), ktora sa odkazuje na clensku premennu this.y, tak sa v objekte eventSetter bude odkazovat na premennu eventSetter.y a nie objektKtoryChcem.y)....
2, Mame rodicovsky objekt Navigation, od ktoreho odvadzame. Ten sa vola Navigation. Tam mame definicie vsetkych clenskych premennych a vsetkych funkcii, ktore sa volaju.
3, Mame dcersky objekt navigation odvodeny od Navigation. Tento dcersky objekt je zaujimavy v tom, ze pri jeho konstruovani (new Navigation) do neho dame nejake konkretne hodnoty (konkretny obrazok ktory posuvame) a podobne...

Trochu mimo temy zdvovodnenie:
Dovod rozdelenie na rodicovsky a dcersky objekt sa da predstavit napriklad, ak by som nerobil takuto navigaciu, ale robil klasicke menu, ktore ma povedzme hover efekt.
Vytvorim si jednu predlohu, ktorej poviem ako sa to menu sprava, ze si ma nacitat vsetky polozky z hlavneho itemu a tym menit triedy.
Potom cez operator NEW vytvorim KONKRETNE menu, ktoremu urcim CO JE TEN HLAVNY ITEM. Ale tie instancie mozem spravit aj 2 alebo 3 alebo X roznych, a aj tak sa to menu bude spravat vsade rovnako. Nebudu si ale medzi sebou superit, lebo kazdy z nich bude mat svoj vlastny set poloziek submenu, ktore si kazda jedna instancia odvodi od svojho vlastneho hlavneho prvku, ktory dostane ako parameter.....

Spat k teme:
Ked mam
Kód: Vybrat vše
eventSetter.addHandler(getElementById('mainImage'), "click",_nejakaFce);
Tak to znamena, ze sa vezme definicia funkcie "_nejakaFce" (kludne si to daj takto alertnut, uvidis definiciu danej funkcie. Proste sa tam natvrdo prenesie jej zdrojak...) a ta sa vlozi do eventSetter-u a tam sa vykona. TEDA MA TA FUNKCIA SCOPE eventSetter. Keby som na clensku premennu nepouzival klucove slovicko this, ale pouzival by som "Navigation", tak by som sa aj napriek tomu, ze som v scope eventSetter dostal k rodicovskemu objektu, pretoze v scope eventSetter by sa nic nenaslo, takze by sa prislo do vyssieho scope-u = globalneho (scope window, document, alebo si to este mozes inak pomenovat). Tam uz Navigation definovane JE! Takze ho tam najde... A zavola sa tato clenska premenna. Problem ale nastane, pokial chcem VIAC AKO 1INSTANCIU. Pretoze pri tvoreni mu nemozem povedat, ze ta clenska premenna nebude ani "this" ani "Navigation", ale ze bude "navigation", pripadne ak by som pouzil
Kód: Vybrat vše
var ukulele=new Navigation(...);
, tak to bude v tomto pripade to "ukulele". A samozrejme nemozem pouzit slovicko Navigation, pretoze by mi kazda jedna instancia prepisovala hodnoty tej predchadzajucej...

Takze este raz sa pytam. Nevie niekto sposob, ako predat nieco miesto otaznikov do
Kód: Vybrat vše
]eventSetter.addHandler(getElementById('mainImage'), "click", ???)
tak, aby sa mi spustilo navigation.mojafunkcia V SCOPE navigation?

Uf dufam, ze teraz ma uz vsetci pochopili... :)

-- 26. 7. 2010 22:51 --

Uf! Tak dlho som to vysvetloval, az som nakoniec nasiel odpoved... Staci vytvorit sprostredkovatelsku funkciu, ktorej ako argumenty predame objekt z ktoreho kontextu chcem kod vykonavat, samotnu funkciu a dalsie pripadne argumenty...

Sprostredkovatelska funkcia potom vyzera nejak takto:
Kód: Vybrat vše
function callFromOtherContext(contextObject,functionCode)
{
   var args = Array.prototype.slice.call(arguments, 2);
   return function()
      {
         allArguments = args.concat(Array.prototype.slice.call(arguments));
         functionCode.apply(contextObject, allArguments);
      };
}

A pouziva sa nejak takto:
Kód: Vybrat vše
eventSetter.addHandler(
   getElementById('mainImage'), "click",callFromOtherContext(
      navigation, navigation.goLeft
   )
);
gandor
Mírně pokročilý

Odeslat příspěvekod eskjuell 27. 7. 2010 09:03

Tak tohle by mě ani ve snu nenapadlo :-))
hmm..., koblížky
eskjuell
Junior
Uživatelský avatar


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků