wib: Wie löscht man ein Objekt aus sich selbst heraus?

Hi,

ich habe ein Objekt mit der Methode delete(), doch diese Methode verhält sich nicht wie ich erwartet habe. Sie soll eigentlich das gesamte Objekt löschen, indem sie diese Funktion aufruft:

function deleteObj(obj) {
  return delete obj;
}

In dem Objekt gibt es noch andere Methoden, zum Beispiel
DOMelement.onclick = function() {
  self.close(); // Am Anfang des Objekts wird self = this; deklariert.
}

Mit den Objekten und Referenzen ist das ja in JS nicht immer ganz einfach. Ich habe gelesen, dass alle Referenzen zu einem Objekt gelöscht werden müssen, bevor man das Objekt selbst löschen kann (reference count muss 0 sein). Also habe ich der Funktion deleteObj() noch dementsprechend erweitert (self = null; alle DOM Objekte entfernen), aber es klappt immernoch nicht.

Hier mal ein Beispiel:

nav = new xWindow(); // Hier wird ein Bereich namens nav erstellt
  /* Hier wird ein Link in nav geschrieben */
  AnewWindow = addElement("a", nav.content);
  AnewWindowText = addText("Create a new xWindow", AnewWindow);
  AnewWindow.href = "javascript:void(0);";
  AnewWindow.onclick = function() { // Wenn man auf diesen Link klickt, soll ein weiterer Bereich erstellt werden...
    if(!window.newX) { // ... es sei denn, es gibt ihn schon
      newX = new xWindow();
      newX.setTitle("A new xWindow");
      newX.close(); // der Bereich soll geschlossen werden, klappt aber nicht
    } else {
      alert(newX.title);
    }
  }
  AnewWindow = null; // (Memory leak verhindern)

Wenn man auf den Link klickt, öffnet sich ein neuer Bereich. Er wird kurz darauf wieder geschlossen. newX soll gelöscht werden. Wenn man wieder auf den Link klickt, kommt aber alert mit "A new xWindow".
Wenn ich in an entsprechenden Stellen im Code testweise mal
delete newX;
einfüge, wird newX natürlich korrekt gelöscht, aber es kann ja auch sein, dass das Objekt mal einen anderen Namen hat.

Wie lösche ich also newX mit folgendem Aufruf:
newX.close();
?

Jetzt bin ich mal gespannt :)
Grüße, wib!

  1. function deleteObj(obj) {
      return delete obj;
    }

    delete funktionert nur mit globalen Objekten, wenn ich das richtig in Erinnerung habe.
    http://de.selfhtml.org/javascript/sprache/operatoren.htm#delete
    http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator

    Aber eigentlich braucht man den auch nicht in JS, zumindest wüßte ich nicht wozu.

    Struppi.

    --
    Javascript ist toll (Perl auch!)
    1. delete funktionert nur mit globalen Objekten, wenn ich das richtig in Erinnerung habe.

      Ich habe aber nunmal nur eine Referenz zu dem Objekt, dass ich löschen will. Das Objekt selbst ist global deklariert.

      Aber eigentlich braucht man den auch nicht in JS, zumindest wüßte ich nicht wozu.

      Das habe ich doch genau erklärt. Ich will ein Objekt löschen, aber ich kriege es nicht zu fassen, sondern immer nur die Referenzen dazu.
      Das muss es doch geben?

      Grüße

      1. delete funktionert nur mit globalen Objekten, wenn ich das richtig in Erinnerung habe.
        Ich habe aber nunmal nur eine Referenz zu dem Objekt, dass ich löschen will. Das Objekt selbst ist global deklariert.

        und nicht mit var deklariert?

        Aber eigentlich braucht man den auch nicht in JS, zumindest wüßte ich nicht wozu.
        Das habe ich doch genau erklärt.

        Hast du?
        Funktioniert obj = null nicht?

        Struppi.

        --
        Javascript ist toll (Perl auch!)
        1. delete funktionert nur mit globalen Objekten, wenn ich das richtig in Erinnerung habe.

          Nein, geht immer und überall.

          Ich habe aber nunmal nur eine Referenz zu dem Objekt, dass ich löschen will. Das Objekt selbst ist global deklariert.

          und nicht mit var deklariert?

          Nein. Es befindet sich in einer Funktion init() und soll im globalen name space sein.

          Aber eigentlich braucht man den auch nicht in JS, zumindest wüßte ich nicht wozu.
          Das habe ich doch genau erklärt.

          Hast du?

          Jepp. Stell dir vor ich habe ein dynamisch erzeugtes Objekt, welches ein Fenster (Kein Browserfenster, sondern ein DIV) darstellt und kontrollieren kann. In dem Fenster gibt es auch ein kleines Kreuz, und wenn man darauf klickt, soll das Fenster und das Objekt gelöscht werden.

          Funktioniert obj = null nicht?

          in deleteObj(obj)? Nein.
           wib

          1. delete funktionert nur mit globalen Objekten, wenn ich das richtig in Erinnerung habe.
            Nein, geht immer und überall.

            Du hast die Seiten gelsen die ich dir gezeigt habe, da steht was anderes.

            Ich habe aber nunmal nur eine Referenz zu dem Objekt, dass ich löschen will. Das Objekt selbst ist global deklariert.

            und nicht mit var deklariert?
            Nein. Es befindet sich in einer Funktion init() und soll im globalen name space sein.

            Wenn das so ist dann sollte delete funktionieren.

            Aber eigentlich braucht man den auch nicht in JS, zumindest wüßte ich nicht wozu.
            Das habe ich doch genau erklärt.

            Hast du?
            Jepp. Stell dir vor ich habe ein dynamisch erzeugtes Objekt, welches ein Fenster (Kein Browserfenster, sondern ein DIV) darstellt und kontrollieren kann. In dem Fenster gibt es auch ein kleines Kreuz, und wenn man darauf klickt, soll das Fenster und das Objekt gelöscht werden.

            Warum soll das Objekt gelöscht werden, das ist keine Erklärung, das ist das was du willst, aber nicht warum. Und deine Süffisanz kannst du dir sparen, ich kann mir durchaus vorstellen was du da machst.

            Funktioniert obj = null nicht?

            in deleteObj(obj)? Nein.

            Wieso nicht?
            könntest du dir mal die Mühe machen genau zu erklären was du willst, schließlich willst DU Hilfe, nicht ich.

            Struppi.

            --
            Javascript ist toll (Perl auch!)
            1. Ja, gut. Hatte es auch in gut geschrieben, aber habe das Fenster aus Versehen geschlossen und musste alles nochmal schreiben, deswegen ist alles ein bischen kurz geraten. Dessen ungeachtet, ich hatte alles erklärt.
              Das Objekt xWindow erstellt also ein Fenster mit allem drum und dran. Hier ist init():
              function init() {
                nav = new xWindow();
                /*EinLink sei ein Link-Objekt.*/
                EinLink.onclick = function() {
                  if(!window.newX) { // Ein neues Fenster namens newX soll nur erstellt werden, wenn es newX nicht bereits gibt. Deswegen muss, wenn newX geschlossen werden soll, auch das Objekt newX gelöscht werden, nicht nur die entsprechenden DOM Elemente. Aber das ist nicht der Einzige Grund; wenn man 1000 Fenster öffnet und wieder schließt, müssen die Objekte gelöscht werden, sonst bleiben die im Speicher.
                    newX = new xWindow();
                    newX.setTitle("A new xWindow");
                    newX.close();
                  } else {
                    alert(newX.title); // newX.close() hat zwar das DIV gelöscht, aber das Objekt selbst ist noch vorhanden, inklusive der Eigenschaft title, die hier zum Test ausgegeben wird. (wenn ich nocheinmal auf den selben Link klicke)
                  }
                }
              }

              Funktioniert obj = null nicht?
              »»
              in deleteObj(obj)? Nein.

              Wieso nicht?
              könntest du dir mal die Mühe machen genau zu erklären was du willst, schließlich willst DU Hilfe, nicht ich.

              Stimmt. obj = null; geht nicht, weil man damit die Referenz zu newX gleich null stellt, nicht aber newX selbst.
              Auch delete obj; löscht nur die Referenz. Genau hier liegt das Kernproblem.
              Und ich muss das Objekt löschen, sonst ist nach kurzer Zeit der Speicher voll.

              1. Ja, gut. Hatte es auch in gut geschrieben, aber habe das Fenster aus Versehen geschlossen und musste alles nochmal schreiben, deswegen ist alles ein bischen kurz geraten. Dessen ungeachtet, ich hatte alles erklärt.

                Wie auch immer
                Ich lese aus den etwas konfusen darstellungen, dass du erwartest, dass alles verschwindet, was im zusammenhang mit deinem JS Objekt steht, das ist aber nicht so. Für die Elemente des DOM bist du selber zuständig.

                if(!window.newX) { // Ein neues Fenster namens newX soll nur erstellt werden, wenn es newX nicht bereits gibt. Deswegen muss, wenn newX geschlossen werden soll, auch das Objekt newX gelöscht werden, nicht nur die entsprechenden DOM Elemente. Aber das ist nicht der Einzige Grund; wenn man 1000 Fenster öffnet und wieder schließt, müssen die Objekte gelöscht werden, sonst bleiben die im Speicher.

                Wer sagt das?

                Meines Wissens hat JS eine garbage collection und kümmert sich um die Speicherverwaltung weitestgehend alleine.

                alert(newX.title); // newX.close() hat zwar das DIV gelöscht, aber das Objekt selbst ist noch vorhanden, inklusive der Eigenschaft title, die hier zum Test ausgegeben wird. (wenn ich nocheinmal auf den selben Link klicke)

                auch nach newX = null?

                Struppi.

                --
                Javascript ist toll (Perl auch!)
                1. Ich lese aus den etwas konfusen darstellungen, dass du erwartest, dass alles verschwindet, was im zusammenhang mit deinem JS Objekt steht, das ist aber nicht so. Für die Elemente des DOM bist du selber zuständig.

                  Nee, sorry, die DOM Elemente lösche ich selbst, danach soll das Objekt entfernt werden.

                  if(!window.newX) { // Ein neues Fenster namens newX soll nur erstellt werden, wenn es newX nicht bereits gibt. Deswegen muss, wenn newX geschlossen werden soll, auch das Objekt newX gelöscht werden, nicht nur die entsprechenden DOM Elemente. Aber das ist nicht der Einzige Grund; wenn man 1000 Fenster öffnet und wieder schließt, müssen die Objekte gelöscht werden, sonst bleiben die im Speicher.

                  Wer sagt das?

                  Meines Wissens hat JS eine garbage collection und kümmert sich um die Speicherverwaltung weitestgehend alleine.

                  Ja, das ist ja auch richtig, aber der garbage collector entfernt natürlich nur Dinge, die entweder nicht mehr gebraucht werden oder aber die man mit dem delete operator löscht.

                  Anfang Versuchsaufbau:

                  test = new Foo();

                  alert(test.bar); // Ich würde undefined erwarten, aber test wurde nicht gelöscht, also kommt "bar".

                  function Foo() {
                        this.bar = "bar";
                        this.deleteMyself = deleteObj;
                        this.deleteMyself(); // Dieses Objekt soll sich mit dieser Methode selbst löschen
                      }

                  function deleteObj() {
                        return delete this; // this bezieht sich hier nicht auf deleteObj, sondern auf Foo, um das mal gleich vorwegzunehmen. Die Funktion gibt false zurück, "this" kann also nicht gelöscht werden. Wieso nicht? Wenn ich return delete this.bar; schreibe, wird test.bar tatsächlich gelöscht und alert(test.bar); gibt undefined aus.
                      }

                  Ende Versuchsaufbau.

                  auch nach newX = null?

                  newX = null funktioniert, aber das kann ich innerhalb des Objekts oder iner seiner Methoden nicht anwenden, weil das Fenster ja nicht unbedingt newX heißen muss.

                  1. Anfang Versuchsaufbau:

                    test = new Foo();

                    alert(test.bar); // Ich würde undefined erwarten, aber test wurde nicht gelöscht, also kommt "bar".

                    function Foo() {
                          this.bar = "bar";
                          this.deleteMyself = deleteObj;
                          this.deleteMyself(); // Dieses Objekt soll sich mit dieser Methode selbst löschen
                        }

                    function deleteObj() {
                          return delete this; // this bezieht sich hier nicht auf deleteObj, sondern auf Foo, um das mal gleich vorwegzunehmen. Die Funktion gibt false zurück, "this" kann also nicht gelöscht werden. Wieso nicht? Wenn ich return delete this.bar; schreibe, wird test.bar tatsächlich gelöscht und alert(test.bar); gibt undefined aus.
                        }

                    Ende Versuchsaufbau.

                    Das ist klar, du kannst delete nur auf die Variabel anwenden die das Objekt erzeugt. Das Objekt selber kann sich nicht löschen, ist aber auch nicht nötig.

                    auch nach newX = null?

                    newX = null funktioniert, aber das kann ich innerhalb des Objekts oder iner seiner Methoden nicht anwenden, weil das Fenster ja nicht unbedingt newX heißen muss.

                    Also doch keine globale Variabel. Du musst die Variabel löschen die mit dem Objekt verbunden ist, also in deinem Fall ist es sinnvoll ein neues Fenster nicht unmittelbar zu erzeugen, sondern dies in einem Objekt zu kapseln, das alle Referenzen auf deine Objekte vorhält und dann dort das jeweilige Objekt zu löschen, einen anderen Weg gibt es nicht.

                    Struppi.

                    --
                    Javascript ist toll (Perl auch!)
                    1. Ein Objekt kann sich unter keinen Umständen selbst löschen?
                      Wäre doch cool, wenn man einfach soetwas wie
                      Object.selfDestruct();
                      machen könnte.

                      Dein Vorschlag ist aber sehr gut, ich werde ein übergeordnetes Objekt diese Aufgabe übernehmen lassen. Mensch, eigentlich ganz einfach.

                      1. Hallo,

                        Wäre doch cool, wenn man einfach soetwas wie
                        Object.selfDestruct();
                        machen könnte.

                        Dann wäre das Forum voll von Einträgen von Leuten, die sich wundern, warum eine Funktion:

                        function test () {
                           this.selfDestruct();
                           return(true);
                        }

                        nichts mehr zurückliefert ;-)

                        Davon abgesehen:

                        Nach meinem Dafürhalten löscht man auch mit

                        delete objekt;

                        kein Objekt (sofern objekt wirklich ein Objekt und kein primitiver Datentyp ist), sondern immer nur die Refernz darauf.

                        Denn da alle Objekte in JS als Referenzen übergeben werden, wird "delete" damit auch nur eine Referenz übergeben.

                        Allerdings:
                        Wird die letzte Referenz gelöscht, springt der Garbage-Collector an und gibt auch den Speicherbereich, auf den die Referenz gezeigt hat, frei.

                        Jörg

                        Dein Vorschlag ist aber sehr gut, ich werde ein übergeordnetes Objekt diese Aufgabe übernehmen lassen. Mensch, eigentlich ganz einfach.

            2. das xWindow Objekt unterstützt soetwas wie pseudo event handler, ich kann also folgendes machen:

              newX = new xWindow();
                newX.setTitle("A new xWindow");
                newX.onclose = function() {
                  delete newX; // funktioniert.
                  return true;
                }

              Dann wird newX wie erwartet gelöscht. Das Problem:
              Der onclose handler kann, wie jeder event hander, nur eine Funktion enthalten, es würde also schwierig werden, später einen event handler hinzuzufügen.
              Außerdem würde das für jedes Fenster, das ertzeugt wird, 4 Zeilen Code hinzu, die für jedes Fenster gleich sind. Diese Zeilen will ich nicht aus Faulheit vermieden, sondern weil es eben unsauber ist.
              Was ich mir wünsche:
              Diese Funktionalität für jedes Fenster, dass erstellt wird. Daher muss es im Objekt die entsprechende Funktion geben. In einer solchen Funktion kann ich natürlich nicht den Namen "newX" verwenden, das Fenster kann ja ganz anders heißen. this oder self funktionieren aber leider auch nicht (delete this; geht gar nicht, delete self; löscht die Referenz "self").
              Ja, ich weiß nicht, besser kann ichs glaub ich nicht erklären, aber ich versuchs gerne weiter.

              1. das xWindow Objekt unterstützt soetwas wie pseudo event handler, ich kann also folgendes machen:

                newX = new xWindow();
                  newX.setTitle("A new xWindow");
                  newX.onclose = function() {
                    delete newX; // funktioniert.
                    return true;
                  }

                Dann wird newX wie erwartet gelöscht. Das Problem:
                Der onclose handler kann, wie jeder event hander, nur eine Funktion enthalten, es würde also schwierig werden, später einen event handler hinzuzufügen.

                Dafür gibt es auch Lösungen, im Mozilla addEventListener()

                Außerdem würde das für jedes Fenster, das ertzeugt wird, 4 Zeilen Code hinzu, die für jedes Fenster gleich sind. Diese Zeilen will ich nicht aus Faulheit vermieden, sondern weil es eben unsauber ist.

                Ich halte schon die globale Variabel für unsauber, aber du du nur eine hast kannst du doch im Objekt selber newX auf null setzen.

                Ja, ich weiß nicht, besser kann ichs glaub ich nicht erklären, aber ich versuchs gerne weiter.

                Ich weiß nicht ob du dir nicht zuviel Gedanken über die Speicherverwaltung machst. JS ist nicht Java oder C++, ich habe den delete Operator noch nie benutzt und wüßte auch nicht warum ich das tun sollte, da mir JS die schmutzige Arbeit des aufräumens abnimmt.

                Das einzige worauf du aufpassen musst sind die Speicherlöcher des IE, dazu gibt es aber eine Menge interessanter Artikel die das besser erklären können als ich.

                Struppi.

                --
                Javascript ist toll (Perl auch!)