Struppi: Experten! timeout und Objekt

Hallo alle JS Experten ;-)

Eigentlich ist das keine Frage, sondern ich brauch ein bisschen Input ob und wie ich das neu gelernte am besten umsetze.
Zum Problem:

Fast jeder kennt das Problem man bastelt sich ein schönes Objekt und dann möchte man mit diesem einen timer benutzen. Das geht aber nicht, da die funktion setTimeout einen string als ersten Parameter erwartet und ein Objekt als String darzustellen ist nicht möglich.

Nun hab ich (ich glaube es war der JS Newsgroup) einen schönen Trick/workaround gelesen, der auch sogar im IE 4 funktionert.

Das sieht so aus:
<script type="text/javascript">
function myObj(name)
{
    this.name = name;
    this.wert = 0;
}
myObj.prototype.timer = function()
{
    if( this.wert && !confirm('Der Zähler ist bei: ' + this.wert + '\n\nWeiter?') ) return;
    this.wert++;
    window.setTimeout(this.name + '.timer()', 500);
}

var o = new myObj('o');

o.timer();

</script>

http://home.arcor.de/struebig/computer/javascript/test/test timeout.html

Geht das eleganter?
(ich weiss dass man in neuren Browsern auch ein anonyme Funktion definieren kann, das läuft aber nicht in meinem IE 4)

Es ist ja manchmal nicht so einfach den Variabelnname als String zu übergeben (bei einem Array z.b.), kann man den zur Laufzeit irgendwie rausfinden?

Gibt es vielleicht in den Tiefen von .prototype .constructor usw. noch andere Möglichkeiten?

Und wo geht das nicht?

Struppi.

  1. Hallo Struppi,

    Geht eigentlich ganz einfach:

    <script type="text/javascript">
    function myObj(name)
    {
        this.name = name;
        this.wert = 0;
    }

    window.setTimeout(myObj(),1000);

    </script>

    Wie nachzulesen, erwartet settimeout auch einen Zeiger auf ne Funktion.
    Also einfach den Funktionsnamen als Argument übergeben.

    window.setTimeout ( vCode, iMilliSeconds [, sLanguage] )

    Parameters

    vCode Required. Variant that specifies the function pointer or string that indicates the code to be executed when the specified interval has elapsed.

    Gruss
    Oliver

    1. Geht eigentlich ganz einfach:

      Nö, eben nicht.

      <script type="text/javascript">
      function myObj(name)
      {
          this.name = name;
          this.wert = 0;
      }

      window.setTimeout(myObj(),1000);

      Das wäre ja nicht myObj
      Sondern du musst erst eins anlegen:

      var o = new myObj();

      und jetzt?
      wie gesagt ich möchte innerhalb des Objetes zur Laufzeit einen Timer setzten. Das ist zum Beispiel nötig, wenn du einen Layer langsam über den Bildschirm bewegen möchtest und diesen als Objekt definierst.

      Dazu musst du die Bewegen Funktion immer wieder aufrufen, das würde bei dir so aussehen:

      function myObj(name)
      {
      this.name = name;
      this.wert = 0;
      }
      myObj.prototype.move = function()
      {
            if(this.wert < ende) window.setTimeout(this.move(),1000);
      }

      var o = new myObj();
      var ende = 100;
      o.move();

      klapt aber nicht.

      </script>

      Wie nachzulesen, erwartet settimeout auch einen Zeiger auf ne Funktion.
      Also einfach den Funktionsnamen als Argument übergeben.

      Wo hast du das gelesen?
      http://www.mozilla.org/docs/dom/domref/dom_window_ref115.html#1021427

      schreibt:
      ID = window.setTimeout("funcName", delay)

      Parameters

      funcName is the name of the function for which you want to set a delay.

      vCode Required. Variant that specifies the function pointer or string that indicates the code to be executed when the specified interval has elapsed.

      OK hier:
      http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/settimeout.asp

      Das heißt es funktionert zumindest in allen IE Browsern mit einer anonymen Funktion. Aber nicht so wie du es schreibst.

      sondern so:
      function myObj(name)
      {
      this.name = name;
      this.wert = 0;
      }
      myObj.prototype.move = function()
      {
            window.status = 'wert:' + this.wert;
            var s = this;
            if(++this.wert < ende)
            window.setTimeout(function(){s.move()},1000);
      }

      var o = new myObj();
      var ende = 100;
      o.move();

      Ich werd das mal in allen Browsern ausprobieren, ist zumindest flexibler als die mit dem String.

      Struppi.

  2. gruss Struppi,

    Fast jeder kennt das Problem man bastelt sich ein schönes Objekt und dann
    möchte man mit diesem einen timer benutzen. Das geht aber nicht, da die
    funktion setTimeout einen string als ersten Parameter erwartet und ...

    ... ein Objekt als String darzustellen ist nicht möglich.

    richtig - aber man kann die objekt-referenz mit einem string umschreiben:
       http://www.pseliger.de/jsExtendedApi/jsApi.Object.selfReferences.dev.js

    die forums-suche spuckt zwei relevante links aus, in denen der weg
       zur loesung dieses problems hoffentlich nachvollzogen werden kann:
       http://suche.de.selfhtml.org/cgi-bin/such.pl?suchausdruck=selfreference&lang=on&feld=alle&index_5=on&index_6=on&hits=100

    function myObj(name)
    {
        this.name = name;
        this.wert = 0;
    }
    myObj.prototype.timer = function()
    {
        if( this.wert && !confirm('Der Zähler ist bei: ' + this.wert + '\n\nWeiter?') ) return;
        this.wert++;
        window.setTimeout(this.name + '.timer()', 500);
    }
    ...
    Geht das eleganter?

    naja, ob das eleganter waere, weis ich nicht, denn es saehe dann so aus:

    function MyObject() {
         this.setSelfReference();
         this.value = "something";
         //...
       }
       MyObject.prototype.timer = function () {
         if (this.value && !confirm("Der Zähler ist bei: " + this.value + "\n\nWeiter?")) {
           return;
         }
         ++this.value;
         setTimeout(this.getSelfReference() + ".timer()",500);
       };

    um das gefrickel in "setTimeout" kommt man in diesem fall nicht
       drumherum, man spart sich aber die namensgebung!

    ausserdem verwalten sich die referenzen immer dann von selbst,
       wenn eine referenz gesetzt oder geloescht wird. das ist ziemlich
       praktisch, wenn man zur laufzeit mit einer grossen und darueber
       hinaus noch schwankenden anzahl von objekten arbeiten muss, die
       diese art von selbstreferenzierung in anspruch nehmen.

    (ich weiss dass man in neuren Browsern auch ein anonyme Funktion
    definieren kann, das läuft aber nicht in meinem IE 4)

    ob "jsApi.Object.selfReferences.js" im 4er msie laeuft, muss noch
       getestet werden (kein verpflichtender aufruf).

    viel spass beim basteln - peterS. - pseliger@gmx.net

    --
    ie:( fl:) br:> va:| ls:& rl:| n4:} ss:} de:µ js:} zu:]