Tuossa tuli pieni ongelma vastaan kun JS objekteja pyöritteli. Koittanut saada kaiken tarpeellisen toiminnallisuuden suoraan objektiin, siten että voitaisiin luoda uusi objekti per Canvas samalla toiminnallisuudella tässä tapauksessa. Muuten onnistunutki, mutta tuli nyt ongelma kun EventListenereitä alkoi lisäämään.
Eli joudun lisäämään pääobjektissa EventListenerin sen alielementtiin ecanvakseen. Joten tästä EventListenerissä kutsutusta functiosta onMouseMovesta haluaisin päässä käsiksi suoraan tähän pääobjectiin jossa ecanvas on. Koodi on seuraavanlainen:
function Energia_object(canvasElement) { //canvas init this.ecanvas = canvasElement; try { this.econtext = this.ecanvas.getContext('2d'); } catch(ex) { alert("Virhe: " + ex); return false; } this.debug = function(text) { $('#debug').prepend(text + "<br />"); } this.onMouseMove = function(e) { var x=e.clientX-this.offsetLeft+window.pageXOffset; var y=e.clientY-this.offsetTop+window.pageYOffset; this.debug("MouseMove: " + x + ", " + y); } this.onMouseClick = function(e) { var x=e.clientX-this.offsetLeft+window.pageXOffset; var y=e.clientY-this.offsetTop+window.pageYOffset; this.debug("MouseClick: " + x + ", " + y); } this.debug("init"); //event listeners this.ecanvas.addEventListener("click",this.onMouseClick, false); this.ecanvas.addEventListener("mousemove",this.onMouseMove, false); }
Eli haluaisin käyttää mm. tuota this.debug functiota this.onMouseMove function sisällä, mutta ei onnistu, koska tuo this.onMouseMove menee tuohon this.ecanvas elementtiin. Voikohan tuossa AddEventListenerin mukana laittaa tuon pääobjektin tms.
Lisäys:
Tommosella purkka ratkasulla tuo jotenki toimis jos laittais että pääobjectin nimi on sama ko canvaselementin id:
this.onMouseClick = function(e) { var x=e.clientX-this.offsetLeft+window.pageXOffset; var y=e.clientY-this.offsetTop+window.pageYOffset; $.globalEval(this.id + ".debug('purkkaclick')"); }
Mutta tommosen käyttöä välttäis kyllä aika pitkälle.
JavaScriptin this
toimii vähän yllättävällä tavalla. Se, miten funktiota/metodia kutsutaan, vaikuttaa this
:n arvoon sen sisällä.
function Foo1() { this.x = 5; this.get_x = function() { return this.x; }; } var foo = new Foo1(); alert(foo.x); // 5 alert(foo.get_x()); // 5 var get_x = foo.get_x; alert(get_x()); // undefined var x = "kissanpentu"; alert(get_x()); // "kissanpentu"
Kun kutsu on muotoa foo.get_x()
, metodin sisällä this
:n arvo on foo
. Mutta kun funktio on erotettu objektista ja sitä kutsutaan yksinään, get_x()
, sen sisällä this
viittaakin globaaliin objektiin.
Yksi ratkaisu on tällainen:
function Foo2() { var self = this; this.x = 5; this.get_x = function() { return self.x; }; } var foo = new Foo2(); var get_x = foo.get_x; alert(get_x()); // 5
Eli tallennetaan this
:n arvo paikalliseen muuttujaan konstruktorin alussa (nimi voi olla vaikka self
) ja käytetään aina sitä this
:n sijaan metodien sisällä.
Pidän parempana tapana this
:n käyttöä ja kutsujen korjaamista niin, että se asettuu oikein, mutta en nyt jaksa kirjoittaa enempää. :)
Jees tuohan oliki kätevä ja helppo tapa saada tuo toimimaan. Kiitti avusta.
Selfin tilalla näkee usein käytettävän nimitystä that, sillä self saattaa joissakin moottoreissa olla varattu sana, mm. joissakin Operan versioissa tähän muistaakseni törmättiin taannoin userscriptiä tehdessä. Toinen vaihtoehto on tosiaan tehdä bindaukset niin, että this
toimii oikein, tähän esimerkkiä John Resigin kirjoituksesta ECMAScript 5 Strict Mode, JSON, and More.
Aijaa. :o
Entisessä työpaikassa tuon nimi oli aina self
eikä mihinkään siihen liittyviin ongelmiin törmätty. Muissakin koodeissa olen törmännyt samaan nimeen. Löysin nyt Googlella joitain valituksia siitä että globaaliin self
-muuttujaan (eli window.self
:iin) ei voisi asettaa Operassa, mutta eihän kukaan tuollaisia globaaleja tee. ;)
Minusta that
on aika epäintuitiivinen nimi, mutta sitäkin kyllä näkee käytettävän ja kaikkeenhan tottuu.
Ei toki ;). Miusta molemmat that ja self on vähän kehnoja nimiä eri syistä. Heitetään soppaan vielä ehkä omasta mielestä selkein kun en äsken sitä muistanut, eli _this, sitäkin näkyy käytettävän.
Aihe on jo aika vanha, joten et voi enää vastata siihen.