ugrás a tartalomhoz

Objektumon belül a this élérése eseményre

sanyoo · 2008. Jún. 10. (K), 18.15
Jó napot. Volna egy kis segítségre szükségem. Mese helyett kód:

function Class (parameter) {
	this.parameter=parameter;
	document.body.onclick=function () {
		alert(this.parameter);	//Itt szeretném visszakapni az "1" illetve a "2" őt
	}
}
o1=new Class("1");
o2=new Class("2");
Az oké hogy a this értéke a megnyitási környezet miatt olyan amilyen (jelen esetben "document.body") de hogyan lehet kijátszani, illetve megkerülni?

Globális változott (tömböt stb.) kerülném, maradjon csak a objektumon belül. És valóban szeretnék több példány létrehozni az "osztályból" más más értékekkel.
(az Class illetve az osztály megfogalmazásért bocsánat tudom osztály nincs)
Köszönöm előre is a válaszokat.
 
1

closure

vbence · 2008. Jún. 10. (K), 18.43
Ez így fog működni:

function Class (parameter) {  
    this.parameter=parameter;
    var segedvaltozo = this;
    document.body.onclick=function () {  
        alert(segedvaltozo.parameter);  //Itt szeretném visszakapni az "1" illetve a "2" őt
        // vagy egyszerűen
        alert(parameter);  //itt a paraméterlistából éred el, tehát nem this.* -ként
    }  
}  
o1=new Class("1");  
o2=new Class("2");
A beágyazott függvényed örökli az őt futtató környezet (függvény) minden változóját, és így tovább. A this kivétel, mivel az egy speciális változó...
3

closure + iteráció

toxin · 2008. Jún. 11. (Sze), 08.06
(closure, wiktionary szerint magyarul: zárlat) ha egy iteráción belül hozunk létre zárlatos :) függvényt, előbbi függvény meghívásakor az iterátor utoljára felvett értékét fogjuk benne elérni, kivéve ha az aktuális scope elkapását a zárlatos függvény körüli anonim /névtelen függvénnyel megoldjuk

ami nem jó :

        <script type="text/javascript">
            (function (){
                
                var $ = function(id){return document.getElementById(id)};
                        
                myAjaxPageLoader = {		
                    
                    init : function(){
                        var links = $('menu').getElementsByTagName('a'), 
                            self = this;						
                        for (var i=0;i<links.length;i++){
                            // beágyazott függvény meghivásakor (linken kattintva) az iterátor utoljára felvett értékét érjük el 3 			
                            links[i].onclick = function(){
                                // links[3] nem létezik, hibát kapunk									
                                self.fetchPage(links[i].href);
                                return false;
                            };							
                        };
                    },					
                    fetchPage : function(page){
                        alert('Fetching...' + page);
                    }
                };
            })();
            window.onload = function(){
                myAjaxPageLoader.init();
            }
        </script>
    </head>
    <body>
        <div id="menu">
            <a href="index2.html">2.oldal</a>
            <a href="index3.html">3.oldal</a>
            <a href="index4.html">4.oldal</a>
        </div>
ami jó :

        <script type="text/javascript">
        	(function (){
				
				var $ = function(id){return document.getElementById(id)};
						
				myAjaxPageLoader = {		
					
					init : function(){
						var links = $('menu').getElementsByTagName('a'), 
							self = this;
						for (var i=0;i<links.length;i++){							
							(function(){
								// névtelen függvény call objektumában eltároljuk az iterátor aktuális értékét
								var link = links[i];
								link.onclick = function(){
									// így a hívás pillanatabán is megfelelő értéket fog visszaadni
									self.fetchPage(link.href);
									return false;
								};
							})();
						};
					},
					
					fetchPage : function(page){
						alert('Fetching...' + page);
					}
				};
			})();
			window.onload = function(){
				myAjaxPageLoader.init();
			}
        </script>
    </head>
    <body>
    	<div id="menu">
	    	<a href="index2.html">2.oldal</a>
			<a href="index3.html">3.oldal</a>
			<a href="index4.html">4.oldal</a>
		</div>
elég könnyű elfelejteni, főleg ha idegen kódban kezdünk dolgozni (héten nekem is sikerült) figyeljünk oda rá

üdv Csaba
5

Nincs egészen megoldva a problámám.

sanyoo · 2008. Jún. 11. (Sze), 13.57
Mindenkinek köszönöm a válaszait de:
Nem konkrétan toxin nak szól (minden hozzászólnak):
Előszöri a fenti példám valóban csak egy példa volt, mert igazából nem az objektumnak átadott paramétert akarom visszakapni hanem az objektum egy this értéket (konkrétan date de olyan date ami mindegyik objektumban más más értékű).
Másodszor írtam hogy kerülném a globális változókat. Nem lehetne máshogy? Csak így hogy self:this; ? Egyébként így mindig az utolsó példány this értékét kapnám vissza vagy nem?
Módosított példám:

function Class() {
	this.date=new Date();
	document.body.onclick=function () {
		//this.date re lenne szükségem, ami más más értékű az "o1" illetve az "o2" példányban.
	}
}
o1=new Class();
o2=new Class();
toxin: A fenti példádból az elsőt értem hogy miért nem jó. De a másodikban azt nem értem hogy miért kell egy névtelen függvényt létrehozzál? Kipróbáltam a névtelen függvény nélkül valóban nem megy de nem értem miért nem. Ha szépen megkérlek elmagyaráznád?
Ustak: Valóban a apply és a call függvényt a ma napig nem értem igazán. Megérteni a példákat megértem (nagyrészt) de írni nem tudnék. Majd utánanézek jobban mert valóban ezt is a rendbe kéne tenni a fejemben. Egyébként nem akarnál róla írni egy cikket? (metaprogramozzás..)
6

ajánlom figyelmedbe az 1. hozzászólást

vbence · 2008. Jún. 11. (Sze), 14.40
...immár kiemelve ezt a 3 sort:

    var segedvaltozo = this;  
    document.body.onclick=function () {    
        alert(segedvaltozo.parameter);  //Itt szeretném visszakapni az "1" illetve a "2" őt  
Itt ugynanazt adod át, ahova a this mutat a befogadó függvényben.
7

sorry.

sanyoo · 2008. Jún. 11. (Sze), 16.23
Bocsi. igazad van. Ezt elnéztem.
Viszont toxin második példáját mindig nem értem hogy miért kell oda egy névtelen fg létrehozni? Miért nem megy anélkül?
És ismét nagyon köszönöm az eddigi segítséget.
8

magyarázat (változók deklarálása)

vbence · 2008. Jún. 11. (Sze), 18.38
Reméltem, hogy ezt Csaba fogja megválszolni... :)

Ha egy függvényen belül szerepel, hogy var valami akkor egy új változó fog létrejönni. Az eseménykezelő ezt a futási környezetet fogja rökölni benne a valami-vel, ami csak neki szól.

Ha egy ciklusban készíted a beágyazott függvényeket, mind a ciklus futási környzetét fogják örökölni, azaz ugyazat az i-t fogják mind használni.

Hiába nyomod be a cilusba a var-t pl:

var i;
var f = new Array();
for (i=0; i<10; i++) {
    var seged = i;
    f = function () {
        alert(seged);
    }
}
f[1]();
f[2]();
mert a változódeklarációk a futási környezet inicializálásakor (a függvény elején) futnak le, tehát valójában ez fog futni:

var i;
var f;
var seged;

f = new Array();
for (i=0; i<10; i++) {
    seged = i;
    f[i] = function () {
        alert(seged);
    }
}
f[1]();
f[2]();

az örökölt futási környzetben viszont egy darab [i]seged vagy i szerepel, ezen ostoznak a beágyaott függvények.

Ha egy burkoló fv-t használunk, mindegyik új függvényen belül deklarált var újabb változót eredményez.

(Nagyjából... - Most nem volt kedvem véignézni az ECMA szabványt a megfelelő kifejezésekről stb..)
9

Azthiszem értem.

sanyoo · 2008. Jún. 11. (Sze), 19.32
Nagyon szépen köszönöm. Sokat tanultam ma.
12

dolgoztam :)

toxin · 2008. Jún. 11. (Sze), 20.19
de az überlink ill. a faq a zárlatos függvény-closure témához íme: http://jibbering.com/faq/faq_notes/closures.html

üdv Csaba
4

késő

bandi · 2008. Jún. 11. (Sze), 09.23
igen, a this nagyon trükkös, asszem Crockford fogalmazott úgy, hogy nagyon későn kötődik, a másik ilyen az arguments, eltartott egy darabig, mire rájöttem, pedig logikus
10

szebb megoldás

Hodicska Gergely · 2008. Jún. 11. (Sze), 19.56
Ennél azért létezik szebb megoldás pont closure-t használva, és nem is olyan régen volt róla szó: http://weblabor.hu/forumok/temak/21247#comment-52480. Ez megy jQuery nélkül is, csak macerásabb lesz elérni az eseményt kiváltó elemet. Mindenhol ahol a függvényt adnád meg (this.method) ott a delegáltat adod meg (delegate(this, this.method)).


Üdv,
Felhő
11

rendben...

vbence · 2008. Jún. 11. (Sze), 20.14
valóban szebb. Bár a "thisHack" azért szemmel követhetőbb :)
13

én is a thisHack-re voksolnék

toxin · 2008. Jún. 11. (Sze), 21.17
bind-olás, vagy delegálás szerintem is zavarossá tud tenni egy kódot, lásd pl. fenti kódom bind-al
       <script type="text/javascript">
            (function (){
                
                var $ 			= function(id){return document.getElementById(id)},
                    bind		= function(f,s){ return function(){ f.apply(s,arguments);} },
                    bindStop	= function(f,s){ return function(){ f.apply(s,arguments); return false;} };
                        
                myAjaxPageLoader = {		
                    
                    init : function(){
                        var links = $('menu').getElementsByTagName('a');							
                        for (var i=0;i<links.length;i++){
                            bind(function(){
                                var link = links[i];
                                link.onclick = bindStop(function(){
                                    this.fetchPage(link.href);
                                },this);
                            },this)();
                        };
                    },
                    
                    fetchPage : function(page){
                        alert('Fetching...' + page);
                    }
                };
            })();
            window.onload = function(){
                myAjaxPageLoader.init();
            }
        </script>
    </head>
    <body>
        <div id="menu">
            <a href="index2.html">2.oldal</a>
            <a href="index3.html">3.oldal</a>
            <a href="index4.html">4.oldal</a>
        </div>
aztán ízlés dolga, aki bírja iq vagy kv-val :)

üdv Csaba
14

szemléletesség

Hodicska Gergely · 2008. Jún. 11. (Sze), 22.34
Én a példát nem érzem igazából ideálisnak. A kérdezőnek az volt baja, hogy van egy osztálya, aminek egy metódusát használja eseménykezelőnek, és azt szeretné, hogy amikor meghívódik, akkor a this mutasson az objektumra. Ez szerintem elég szemléletes és intuitív (nekem is hiányzott, ha nem így volt), nekem fura, hogy inkább használok egy önkényesen használt változót a a this helyett.

Bonyolultabbnak meg nem érzem, kb. minden esetben nem egy függvényt írsz be egy helyre, hanem egy formulát. Ez szerintem elég következetes.


Üdv,
Felhő
2

Thisről...

Ustak · 2008. Jún. 10. (K), 20.00
pontosan nem a témához tartozik, de jó ha tudod a .call vagy .apply metódus működését is:

var a = {
    szamlalo:5
};
var b= {
    szamlalo:10
};
a.novelem = function(ertek) {
    this.szamlalo+=ertek;
}

a.novelem(3); //==>8
a.novelem.call(b,15);    //==>25
a.novelem.apply(b,[15]); //tömbbel dolgozik

Tehát így a this "érvényességét, contexusát" (nem tudom ez e a jó szó a scope-ra) tudod szabályozni.
De!
ha ilyet próbálsz:

b.novelem=a.novelem;
a.novelem(3); //==>8
b.novelem(15); //==>25 mert a this most a b-re mutat, és nem az a-ra mint ahogy az "szokásos" ojjektumorientált nyelvekben. 
Remélem nem írtam túl nagy butaságokat, ha igen majd kijavít valaki. Love metaprograming :)