Miten hemmetis tehään timeri JS luokan sisään?
function Timer(){ var millis = 20; this.tick = tick; this.start = start function start(){ //Ei toimi setInterval("this.tick();", millis); //Toimii this.tick(); this.tick(); this.tick(); this.tick(); this.tick(); this.tick(); this.tick(); } function tick(){ //tiktaktoe } }
Toi ei tietty toimi ku se kutsuu jtn ulkosta funktiota "setInterval()" ja antaa sille parametrina ton kutsuttavan metodin ym.. mut saisko sen sit jotenki toimimaan?
Menisiköhän näillä pienillä muutoksilla?
<html> <head> <script type="text/javascript"> function Timer(){ var millis = 1000; this.tick = tick; this.start = start; function start(){ //Ei toimi setInterval(this.tick, this.millis); //Toimii //this.tick(); this.tick(); this.tick(); this.tick(); this.tick(); this.tick(); this.tick(); } function tick(){ //tiktaktoe document.write("hou<br>"); } } function go() { var testi = new Timer(); testi.start(); } </script> </head> <body onload="go()"> </body> </html>
Testasin Operalla ja Safarilla.
EDIT: Hidas, mutta eri tapa.
Älä pistä koodia lainausmerkkeihin, paitsi ehkä body-tägin onload kentässä. Käytä nimetöntä funktiota. Katso, että olet määritellyt nimen ennen kuin viittaat siihen.
<html> <script type="text/javascript"> function Timer(mark, millis) { var elem = document.getElementById("ruksit") var count = 0; function tick (tgt) { tgt.value += mark; if (++count == 10) { count = 0; tgt.value += '\n'; } } function start () { setInterval (function() { tick(elem); }, millis); } this.tick = tick; this.start = start; this.count = count; } function init () { var timer=new Timer('x',100); timer.start(); var timer2=new Timer('X',400); timer2.start(); } </script> <body onload="init();"> <textarea id="ruksit" rows="20" cols="60"></textarea> </body> </html>
Suotavaa on myös käyttää erillisiä js-tiedostoja. Esimerkin vuoksi yhdessä pompsissa. Toimi mun Operalla.
Vielä erilainen, kommentoitu versio:
<html> <head> <title></title> <script type="text/javascript"> function Timer() { // arvot jotka ovat paikallisia tälle objektille var timer = null; // julkisia muuttujia this.function = null; this.interval = 0; this.start = function () { // tuhoa aiempi asetus jos sellainen on, emme halua monta päällekkäistä kutsua if(timer != null) { clearInterval(timer); } // tarkista aikaväli if( (this.interval > 0) && (typeof this.function == 'function') ) { // nyt luo kutsu funktioon timer = setInterval(this.function, this.interval); // palautetaan true onnistuessa return true; } } this.stop = function () { // onko alustettu? if(timer != null) { // puhdista clearInterval(timer); // nollaa timer timer = null; // palautetaan true onnistuessa return true; } } } // ulkoinen testifunktio jota kutsumme function tick() { // emme voi käyttää += koska se luokiteltaisiin merkkijonolisäykseksi document.getElementById('ticker').innerHTML-=-1; } // toinen testifunktio function tick2() { document.getElementById('ticker2').innerHTML-=1; } // luo objektit joita voimme kutsua mistä vaan var t = new Timer(); var t2 = new Timer(); // pistä asetuksia t.function = tick; t.interval = 500; t2.function = tick2; t2.interval = 100; </script> </head> <body> <div id="ticker">0</div> <p><input type="button" onclick="t.start()" value="Start"></p> <p><input type="button" onclick="t.stop()" value="Stop"></p> <div id="ticker2">0</div> <p><input type="button" onclick="t2.start()" value="Start"></p> <p><input type="button" onclick="t2.stop()" value="Stop"></p> </body> </html>
Aha joo se toimiki siis ihan täl muutoksella:
setInterval("this.tick()", millis); -> setInterval(this.tick, millis);
Mut ongelmana on, ku pitäs päästä käsiks niihin luokan muuttujiin, siis muutenki ku vaan antaa ne parametrina. Mites muutan tuolta tickin sisältä nyt noita luokan ominaisuuksia?
function Timer(){ this.foo = 1; //... function tick(){ this.foo += 2; } //... }
Tässä se ongelma :/
Btw. Te jaksatte tota koodia vääntää, tajusin jo ekasta ton ensimmäisen ongelman :D
Millaisen objektin yrität nyt rakentaa? Ainakin se näyttäisi siltä, että se olisi vain yhtä tiettyä hommaa tekevä objekti. Omassa esimerkissäni (jonka jonku tovi sitten päivitin) oleva objekti on yleiskäyttöisempi kapistus.
Lisäksi koodi jonka postitin jo aiemmin ei pyrkinyt vastaamaan pelkästään ensimmäiseen kysymykseesi, vaan huomioimaan useita eri asioita jotka ongelmaasi liittyvät. Päivitetty koodi muuttaa objektia aavistuksen oliomaisemmaksi (tosin nyt ongelmaksi jää vielä se, että miten voi huomioida intervalin muutoksen).
Muoks!
En voi enää muokata koodia, joten lisäystä tähän:
<html> <head> <title></title> <script type="text/javascript"> function Timer() { // arvot jotka ovat paikallisia tälle objektille var timer = null; // julkisia muuttujia this.function = null; this.interval = 0; this.start = function () { // tuhoa aiempi asetus jos sellainen on, emme halua monta päällekkäistä kutsua if(timer != null) { clearInterval(timer); } // tarkista aikaväli if( (this.interval > 0) && (typeof this.function == 'function') ) { // nyt luo kutsu funktioon timer = setInterval(this.function, this.interval); // palautetaan true onnistuessa return true; } } this.stop = function () { // onko alustettu? if(timer != null) { // puhdista clearInterval(timer); // nollaa timer timer = null; // palautetaan true onnistuessa return true; } } } // ulkoinen testifunktio jota kutsumme function tick(foo) { if(typeof tick.foo == 'undefined') tick.foo = 0; tick.foo += 1; document.getElementById('ticker').innerHTML = tick.foo; } // toinen testifunktio function tick2(foo) { if(typeof tick2.foo == 'undefined') tick2.foo = 0; tick2.foo -= 1; document.getElementById('ticker2').innerHTML = tick2.foo; } // luo objektit joita voimme kutsua mistä vaan var t = new Timer(); var t2 = new Timer(); // pistä asetuksia t.function = tick; t.interval = 500; t2.function = tick2; t2.interval = 100; </script> </head> <body> <div id="ticker">0</div> <p><input type="button" onclick="t.start()" value="Start"></p> <p><input type="button" onclick="t.stop();alert(tick.foo);" value="Stop"></p> <div id="ticker2">0</div> <p><input type="button" onclick="t2.start()" value="Start"></p> <p><input type="button" onclick="t2.stop();alert(tick2.foo);" value="Stop"></p> </body> </html>
"Luokan ominaisuuksia" voi käyttää ihan suoraan sisemmissä funktioissa, koska ne näkyvät sinne. Ei tähän ole keksitty mitään mutkia, vaan niitä voi vain asettaa ja lukea. Tässä esimerkki, missä ajastimen voi käynnistää ja pysäyttää, ja jokaisella ajastimella on sisällä timerId-muuttuja, joka ei näy maailmalle.
Voit kokeilla, että näitä kahta erillistä ajastinta voi erikseen käynnistää ja pysäyttää napeista useita kertoja. Se vakuuttanee skeptisimmän JS-koodarinkin, että molemmilla on oma sisäinen timerId.
<html> <script type="text/javascript"> var timers = []; function Timer(elem, millis, action) { var timerId = undefined; function start () { if (timerId) return; timerId = setInterval(function() { action(elem); }, millis); } function stop () { if (timerId) { clearInterval(timerId); timerId = undefined; } } this.start=start; this.stop=stop; } function init () { var elem = document.getElementById("ruksit"); timers.push(new Timer (elem, 100, function(tgt) { tgt.value += 'X'; })); timers.push(new Timer (elem, 1000, function(tgt) { tgt.value += '.\n'; })); } </script> <body onload="init();"> <textarea id="ruksit" rows="20" cols="60"></textarea><br> <button onclick="timers[0].start();">Ekan käynnistys</button> <button onclick="timers[0].stop();">Ekan pysäytys </button> <button onclick="timers[1].start();">Tokan käynnistys</button> <button onclick="timers[1].stop();">Tokan pysäytys</button> </body> </html>
JavaScriptissä muuttujat elävät niin kauan kuin niihin on viittaus jossakin elävässä objektissa, esimerkiksi funktiossa.
P.S: Toisin kuin ylemmässä aivopieru-koodissa, nuo this-muuttujat kannattaa asettaa vain, jos ne kuuluvut olion julkiseen rajapintaan. Kapseloinnista lienee kyse. Kun jokin on kapseloinut minun viimeisen aivosoluni, niin enhän minä osaa :)
Koodi tulee suoraan päästä, mutta ajatus on testattu ja toimiva. Oikeastaan kyse on lähes samasta kuin yllä, mutta kutsu on eristetty ajastinluokasta (jota ei tässä edes ole).
// Taulukko kaikille kutsuobjekteille var kutsut = new Array(); // Kutsuobjekti function kutsu(objekti, metodi) { // Tiedot talteen this.objekti = objekti; this.metodi = metodi; // Lisätään taulukkoon this.index = kutsut.length; kutsut.push(this); // Kutsuntafunktio this.call = function () { this.objekti[this.metodi](); } // Funktio, joka luo tästä staattisen kutsun this.getStaticCall = function () { var func; // Luodaan funktio, joka viittaa globaaliin kutsutaulukkoon eval("func = function() {kutsut[" + this.index + "].call();};"); return func; } } function objekti() { this.x = 1; this.nosta = function () { this.x += 1; alert("x = " + this.x); } } var o1 = new objekti(); var o2 = new objekti(); var k1 = new kutsu(o1, "nosta"); var k2 = new kutsu(o2, "nosta"); // Pannaan kutsu menemään setInterval(k1.getStaticCall(), 3000); setInterval(k2.getStaticCall(), 4000);
Aihe on jo aika vanha, joten et voi enää vastata siihen.