Az egyik legzavarbaejtőbb JavaScript viselkedés a függvényekben használat
this
tulajdonsághoz kapcsolódik. Ma ezt küldjük a műtőasztalra.
Amikor a JavaScript kódunk lefutatt egy függvényt, akkor a függvényben lévő this
hivatkozás akkor fog a függvényhez kötődni amikor az elkezd futni, nem pedig akkor amikor a függvényt definiáljuk. Alapértelmezés szerint egy objektumon kívüli függvény a window
objektumhoz van kötve, mivel a JavaScript esetében a window
objektum testesíti meg a globális futási környezetet.
A probléma
Ha a függvényt úgy hívjuk meg, nem hivatkozunk a hozzá tartozó objektumhoz akkor elveszítjük a kötést. A legegyszerűbb példa erre amikor a függvényt egy másik függvénynek adunk át paraméterül.
var tesztObjektum = { nev: 'Ez a teszt objektum' , getNev: function() { return this.nev; } }; window.nev = '' ; tesztObjektum.getNev(); // -> 'Ez a teszt objektum' function tesztFuggveny(fgv) { return fgv(); } tesztFuggveny(tesztObjektum.getNev) // -> '' window.nev = 'A window objektum' ; tesztFuggveny(tesztObjektum.getNev); // -> 'A window objektum'
Ez így már gondolom mindenkinek érdekessé teszi a problémát.
bind
Szerencsére a prototype egyből tálcán kínálja a megoldást a bind
és a bindAsEventListener
függvényekkel.
tesztFuggveny(tesztObjektum.getNev.bind(tesztObjektum)); // -> 'Ez a teszt objektum'
Ha egy ciklusban szeretnénk használni a bind
függvényt, akkor jobb ha a kötést csak egyszer hozzuk létre.
//ne így, mert ez minden egyes iterációnál új kötést hoz létre! for (var i = 1; i < 10; ++i) tesztFuggveny(tesztObjektum.getNev.bind(tesztObjektum)); //hanem így var bindeltGetNev = tesztObjektum.getNev.bind(tesztObjektum); for (var i = 1; i < 10; ++i) tesztFuggveny(bindeltGetNev);
bindAsEventListener
Ha szeretnénk eseménykezelőként használni a meghívott függvényt akkor a bindAsEventListener
függvényt kell használnunk. Ez annyiban különbözik a bind
-től, hogy biztosítja, hogy a meghívott függvény első paramétereként átadódjon maga az esemény objektum.
var tesztObjektum = { nev: 'És íme: ' }; function kattKezelo(e) { var tag = Event.element(e).tagName.toLowerCase(); var data = $A(arguments); data.shift(); alert(this.nev + 'Kattintás a ' + tag + '-on További függvény paraméterek: ' + data.join(', ')); } Event.observe(document.body, 'click', kattKezelo.bindAsEventListener(tesztObjektum, 1, 2, 3));
A függvény azt fogja eredményezni, hhogy ha valahová kattintunk a böngészőben, akkor ki fogja írni, hogy melyik DOM elemre kattintottunk, valamint további paraméterként megjeleníti, hogy 1, 2, 3. Vagyis nem vesztette el a csatolást, megkapta az eseményt és a többi paramétert is.
Góranga!
Le a kalappal rrd! Az írásaid kiválóak, haznosak, a filozofikusabbak elgondolkodtatóak. Köszönet a munkádért!
Fox Mulder: köszi 🙂