wahsaga: OO in JS - Objekt löschen/Destruktor?

'nabend allerseits,

versuche mich gerade ein bisschen mit OO in javascript zu beschäftigen, soweit man da davon sprechen kann.

im moment rätsele ich, ob es so etwas wie einen destruktor gibt?

mit delete soll man zwar laut selfhtml ein objekt löschen können - aber das scheint mir nicht innerhalb des objektes selber zu gelingen.

habe folgendes probiert:

function myObj() {
   function loeschen() {
      alert(delete this);
   }
   function meldung() {
      alert(this.blubb);
   }
   this.blubb = "blubb";
   this.blah = meldung;
   this.destruct = loeschen;
}

meinObjekt = new myObj();
meinObjekt.blah();     // alert mit "blubb" erscheint
meinObjekt.destruct(); // alert gibt "true" aus, delete sollte
                       // also erfolgreich gewesen sein
meinObjekt.blah();     // alert mit "blubb" erscheint immer noch,
                       // obwohl es meinObjekt doch jetzt gar nicht mehr geben sollte?

gruß,
wahsaga

--
"Look, that's why there's rules, understand? So that you _think_ before you break 'em."
  1. Tag wahsaga.

    im moment rätsele ich, ob es so etwas wie einen destruktor gibt?
    [...]
       function loeschen() {
          alert(delete this);
       }

    Das alert zeigt dir m.W.n. nur das Ergebnis der Funktion delete an, führt sie aber nicht aus. Vielleicht geht es so:

    function loeschen() {
      delete this;
      if(typeof this == undefined)
        alert("gelöscht");
    }

    [...]
    meinObjekt.destruct(); // alert gibt "true" aus, delete sollte
    meinObjekt.blah();     // alert mit "blubb" erscheint immer noch,

    Nur so eine ungetestete Idee um diese Uhrzeit :-)

    Siechfred

    --
    Zum Testen freigegeben: Siechfreds kleines Weblog
    Wer Fehler findet, bitte an die angegebene E-Mail schicken. Danke.
    1. hi,

      alert(delete this);

      Das alert zeigt dir m.W.n. nur das Ergebnis der Funktion delete an, führt sie aber nicht aus.

      scheint mir recht unwahrscheinlich.
      wie soll eine funktion denn überhaupt ein "ergebnis" haben, wenn sie nicht ausgeführt wird?

      außerdem "funzt" das ja in ähnlichen fällen auch, bspw.

      var wert = 1;
      alert(wert = 3); // zeigt ergebnis des ausdrucks, -> 3
      alert(wert);     // zeigt 3 an, weil wert jetzt diesen wert hat

      gruß,
      wahsaga

      --
      "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
  2. Hallo,

    mit delete soll man zwar laut selfhtml ein objekt löschen können - aber das scheint mir nicht innerhalb des objektes selber zu gelingen.

    Das ist ein Denkfehler Deinerseits. Ein _Innerhalb_ eines _Objektes_ gibt es nicht. Ein Objekt ist eine Entität, die im Arbeitsspeicher instanziert ist. Sie begründet sich auf eine Klasse oder, in JavaScript, auf einen Prototyp. Die Funktion myObj() ist der Prototyp Deines Objekts meinObjekt. Du kannst also mit

    delete meinObjekt;

    Dein Objekt löschen. Du kannst aber nicht im Prototyp eine Methode verankern, die alle auf diesem Prototyp basierenden Objekte löscht. Wolltest Du das erreichen?

    Das Konzept des Destructors ist nicht OOP. Es ist C++-Denken. Auch Java kennt keinen Destructor. Objekte, die nicht mehr benötigt werden, werden einfach beendet (auf NULL gesetzt, Streams geschlossen, Threads finalized). Ein garbage collector kümmert sich dann um das Entfernen aus dem Arbeitsspeicher.

    function myObj() {
       function loeschen() {
          alert(delete this);
       }
       function meldung() {
          alert(this.blubb);
       }
       this.blubb = "blubb";
       this.blah = meldung;
       this.destruct = loeschen;
    }

    meinObjekt = new myObj();
    meinObjekt.blah();     // alert mit "blubb" erscheint
    meinObjekt.destruct(); // alert gibt "true" aus, delete sollte
                           // also erfolgreich gewesen sein

    IE gibt hier, meiner Meinung nach richtigerweise, einen Fehler aus.

    meinObjekt.blah();     // alert mit "blubb" erscheint immer noch,
                           // obwohl es meinObjekt doch jetzt gar nicht mehr geben sollte?

    Doch. Das Objekt "meinObjekt" wurde nicht gelöscht.

    viele Grüße

    Axel

    1. hi,

      Das ist ein Denkfehler Deinerseits. Ein _Innerhalb_ eines _Objektes_ gibt es nicht.

      war vielleicht schlecht formuliert.
      mit "innerhalb" meinte ich, dass ich halt so, wie in meinem beispiel, eine objektmethode definiere, mit deren aufruf sich die jeweilige objektinstanz selber "löschen" kann.

      Die Funktion myObj() ist der Prototyp Deines Objekts meinObjekt. Du kannst also mit
      delete meinObjekt;
      Dein Objekt löschen.

      ja, das war mir bewusst.

      Du kannst aber nicht im Prototyp eine Methode verankern, die alle auf diesem Prototyp basierenden Objekte löscht. Wolltest Du das erreichen?

      nein, ich will im prototyp eine methode verankern, mit der die betreffende objektinstanz _sich selbst_ den garaus machen kann.

      meinObjekt = new Prototyp();
      ...
      meinObjekt.loeschen();

      damit soll meinObjekt sich jetzt selbst "entfernt" haben, durch = null setzen oder wie auch immer.
      ich möchte jedenfalls, dass meinObjekt jetzt im script nicht mehr verfügbar ist.

      ich hatte das statt einer methode, die delete this auszuführen versucht, auch noch mit this = null; probiert, aber da meckert mich die JS-konsole vom firefox mit irgendwas von wegen unerlaubter zuweisung an (genaue meldung gerade nicht parat).

      Objekte, die nicht mehr benötigt werden, werden einfach beendet (auf NULL gesetzt, Streams geschlossen, Threads finalized).

      gerade das würde ich ja gerne aus dem objekt selber heraus machen - eine suizid-methode sozusagen.
      aus dem script heraus mit delete meinObjekt ist ja kein größeres problem.
      ich möchte aber ein objekt haben, dass ein paar aktionen durchführt, und sich danach selber ins nirwana verabschiedet.

      gruß,
      wahsaga

      --
      "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
      1. Hallo,

        war vielleicht schlecht formuliert.
        mit "innerhalb" meinte ich, dass ich halt so, wie in meinem beispiel, eine objektmethode definiere, mit deren aufruf sich die jeweilige objektinstanz selber "löschen" kann.

        Hm, ich habe das OO-Modell anders verstanden. Die Klasse (der Prototyp) ist die Beschreibung der Variablen und Methoden, die ein Objekt ausmachen, die Konstruktionsunterlage also. Objekte entstehen durch die Anwendung dieser Konstruktionsunterlagen (mit dem new Operator). Hierbei entsteht eine Instanz des Objektes im Arbeitsspeicher, die durch eine Variable referenziert wird. Objektinstanzen sind dann hinfällig, wenn sie durch keine Variable mehr referenziert werden. Dann brauchen sie auch keinen Platz mehr im Arbeitsspeicher. Die Destructor-Idee ist, wie gesagt, eine C++ Eigenheit.

        nein, ich will im prototyp eine methode verankern, mit der die betreffende objektinstanz _sich selbst_ den garaus machen kann.

        Das ist in Java(Script) nicht vorgesehen. Der Arbeitsspeicher wird durch die JVM (Java) bzw. den JavaScript-Interpreter (JavaScript) verwaltet. Diese sind zuständig für das Einsammeln von Müll (nicht mehr referenzierte Objekte).

        Bei Java erbt jedes Objekt die Methode Object.finalize(). Die wird immer ausgeführt, wenn der Müllsammler das Objekt schluckt. Das dient dazu, dass der Programmierer hier einige eigene Aktionen des Speichermanagements verankern kann. JavaScript kennt soetwas allerdings nicht, soweit ich weiß.

        ich hatte das statt einer methode, die delete this auszuführen versucht, auch noch mit this = null; probiert, aber da meckert mich die JS-konsole vom firefox mit irgendwas von wegen unerlaubter zuweisung an (genaue meldung gerade nicht parat).

        Das "this" ist in diesem Kontext zwar die aktuelle Objektinstanz, allerdings losgelöst von der Referenzierung, quasi direkter Speicherzugriff. Normalerweise sollte auch "delete this" hier eigentlich einen Fehler bringen. Du würdest _dadurch_ das Speichermanagement durcheinander bringen, weil Du der Referenz (Variable) ihren referenzierten Speicherbereich klaust. Dann gäbe es eine Referenz "meinObjekt" auf nichts, im Gegensatz zu "delete meinObjekt", was die Referenz "meinObjekt" entfernt und somit ein unreferenziertes Objekt im Arbeitspeicher lässt, was dann weggeräumt werden kann.

        ich möchte aber ein objekt haben, dass ein paar aktionen durchführt, und sich danach selber ins nirwana verabschiedet.

        var myObjectReference = new myObject();
        delete myObjectReference;

        Anders geht es, soweit ich weiß, nicht.

        viele Grüße

        Axel

        1. hi Axel,

          nein, ich will im prototyp eine methode verankern, mit der die betreffende objektinstanz _sich selbst_ den garaus machen kann.
          Das ist in Java(Script) nicht vorgesehen. Der Arbeitsspeicher wird durch die JVM (Java) bzw. den JavaScript-Interpreter (JavaScript) verwaltet. Diese sind zuständig für das Einsammeln von Müll (nicht mehr referenzierte Objekte).

          vielen dank erst mal für diese und die weiteren ausführungen.

          ob das objekt wirklich sofort aus dem speicher geputzt wird oder nicht, ist mir eigentlich erst mal wurscht - mir ging es mehr darum, dass ein objekt sich selbst "verabschieden" kann, so dass eine nachfolgende existenzprüfung im weiteren scriptverlauf á la if(!meinObjekt) es nicht mehr "findet".

          na ja, vielleicht bastele ich mir da was anderes für, eine extra eigenschaft objekt.amIactive mit true/false, und frage die dann stattdessen ab ...

          gruß,
          wahsaga

          --
          "Look, that's why there's rules, understand? So that you _think_ before you break 'em."