zurück zur Startseite
  


Zurück XHTMLforum > Webentwicklung (außer XHTML und CSS) > Javascript & Ajax
Seite neu laden Prüfen, ob eine Eigenschaft ein Setter ist

Antwort
 
LinkBack Themen-Optionen Ansicht
  #1 (permalink)  
Alt 12.12.2014, 21:37
Erfahrener Benutzer
XHTMLforum-Mitglied
Thread-Ersteller
 
Registriert seit: 09.10.2010
Beiträge: 154
MitjaStachowiak befindet sich auf einem aufstrebenden Ast
Standard Prüfen, ob eine Eigenschaft ein Setter ist

Hallo,

ich suche eine Möglichkeit, herauszufinden, ob eine Eigenschaft eines Objektes ein Setter ist.

Motivation:

Ich habe ein JS-Modul, das recht komplex ist und unter Umständen viele Objekte erzeugt, die aber nicht unbedingt bis zum verlassen der Seite erhalten bleiben.
Da es in JavaScript keine Destruktoren gibt, und ich nur schwer sicherstellen kann, dass keine Referenzen mehr auf ein Objekt existieren, sodass dieses vom Garbage Collector eingesammelt werden kann, habe ich mir einfach eine eigene free-Methode geschrieben, deren letzte Zeile lautet:
Code:
try { for (var key in Object.keys(this)) delete this[key]; } catch (e) {} for (var key in this) this[key] = undefined;
Dadurch werden alle Eigenschaften und Funktionen des Objektes gelöscht; das Objekt ist danach leer und falls noch irgendwo eine Referenz existiert und auf das Objekt zugreift, so wird dies höchstwahrscheinlich einen Fehler erzeugen und ich kann diese Referenz finden und dafür sorgen, dass sie gelöscht wird.
Nun gibt es das Problem, dass Eigenschaften des Prototypes nicht gelöscht werden können. Ich kann diese nur mit undefined überschreiben. Handelt es sich bei einer dieser Eigenschaften um einen Setter, so wird nicht der Setter überschrieben, sondern eben die Setter-Funktion aufgerufen, was zu Fehlern führen kann.

Also wie kann ich überprüfen, ob eine Eigenschaft ein Setter ist und wenn ja, diesen überschreiben?
Mit Zitat antworten
Sponsored Links
  #2 (permalink)  
Alt 12.12.2014, 21:47
Benutzerbild von protonenbeschleuniger
Verbesserer
XHTMLforum-Kenner
 
Registriert seit: 06.09.2007
Beiträge: 4.977
protonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblick
Standard

Wieso willst du das denn von Hand machen? Der GC von JS erledigt sowas von ganz allein, es besteht keine notwendigkeit so was zu machen, es sei denn du musst irgendwelche alten Bugs im IE beseitigen.
Mit Zitat antworten
Sponsored Links
  #3 (permalink)  
Alt 12.12.2014, 22:53
Erfahrener Benutzer
XHTMLforum-Mitglied
Thread-Ersteller
 
Registriert seit: 09.10.2010
Beiträge: 154
MitjaStachowiak befindet sich auf einem aufstrebenden Ast
Standard

Nun, der Garbage Collector kann das Objekt ja nur dann freigeben, wenn keine Referenz mehr darauf existiert. Und ich habe über 2000 Zeilen an Code, der zum Teil recht komplex verschachtelt ist... Da kommt es manachmal eben vor, dass man eine Referenz übersieht. Eine free-Prozedur brauche ich sowieso, da ja die EventListener freigegeben werden müssen, die das Objekt gesetzt hat. Auch "betreut" ein Objekt verschiedene HTML-Elemente, die in free aus dem DOM entfernt werden. Ohne diese Elemente und die EventListener erfüllt das Objekt seinen Zweck nicht mehr richtig, es treten auch Fehler auf, wenn die Elemente nicht mehr im DOM sind. Da ist es naheliegend, auch alle Funktionen und Eigenschaften zu löschen. So erleichtere ich dem Garbage Collector die Arbeit und finde unnötige Referenzen schneller.

Auf jeden Fall funktioniert das Ganze sehr zufriedenstellend, nur die Getter und Setter machen mir Ärger. Aber darauf zu verzichten wäre genau so doof.
Mit Zitat antworten
  #4 (permalink)  
Alt 12.12.2014, 23:20
Benutzerbild von protonenbeschleuniger
Verbesserer
XHTMLforum-Kenner
 
Registriert seit: 06.09.2007
Beiträge: 4.977
protonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblick
Standard

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
Nun, der Garbage Collector kann das Objekt ja nur dann freigeben, wenn keine Referenz mehr darauf existiert. Und ich habe über 2000 Zeilen an Code, der zum Teil recht komplex verschachtelt ist... Da kommt es manachmal eben vor, dass man eine Referenz übersieht.
Der GC "übersieht" nichts. Wie kommst du auf sowas?
Wir reden über JS, nicht über C/C++, da kannst du keine Referenzen übersehen.

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
Eine free-Prozedur brauche ich sowieso, da ja die EventListener freigegeben werden müssen, die das Objekt gesetzt hat. Auch "betreut" ein Objekt verschiedene HTML-Elemente, die in free aus dem DOM entfernt werden. Ohne diese Elemente und die EventListener erfüllt das Objekt seinen Zweck nicht mehr richtig, es treten auch Fehler auf, wenn die Elemente nicht mehr im DOM sind. Da ist es naheliegend, auch alle Funktionen und Eigenschaften zu löschen. So erleichtere ich dem Garbage Collector die Arbeit und finde unnötige Referenzen schneller.
Das macht der GC alles, wie kommst du auf die Idee ihm etwas "erleichtern" zu können?

Das sind alles Standardabläufe, die für einen GC in dynamischen Programmiersprachen die Grundlage bedeuten. Wenn er das nicht beherrscht, verdient er den Namen nicht.

Es gab aber in älteren IEs Probleme damit. Aber soweit ich das seh war das nur bis IE 8 so und die anderen Browser hatten damit keine Probleme. Und das betraf nur ganz spezielle Fälle, die auch nur ganz spezille Workarouns brauchten.

JavaScript and memory leaks
Memory Leaks

Ich kenne auf jeden Fall kein Framework, dass sich die Arbeit machen würde eine zusätzliche Speicherverwaltung über die eigentliche zu bauen und z.b. ExtJS macht auch sehr viel von dem was du da beschriebst und die kommen auch ohne aus.
Mit Zitat antworten
  #5 (permalink)  
Alt 12.12.2014, 23:58
Erfahrener Benutzer
XHTMLforum-Mitglied
Thread-Ersteller
 
Registriert seit: 09.10.2010
Beiträge: 154
MitjaStachowiak befindet sich auf einem aufstrebenden Ast
Standard

Ich meinte auch nicht, dass der GC etwas übersieht, sondern ich.

Also konkret geht es um mein JS Windows-Projekt: JS Windows

Jedes Fenster hat ein Objekt/ist ein Objekt. Und nach dem schließen des Fensters soll dieses freigegeben werden. Nun kann man aber an allen möglichen Stellen (das schließt z.B. auch andere IFrames ein) Referenzen auf ein Fensterobjekt speichern und es ist eben nicht ganz einfach, sicherzustellen, dass die alle nach free gelöscht werden. Denn der Zugriff auf ein geschlossenes Fenster ist zum Beispiel möglich (vorgesehen), denn einige Fenster müssen wiederherstellbar sein. Würde ich also auf ein explizites Freigeben verzichten, wäre im Prinzip jedes Fenster wiederherstellbar und würde samt HTML-Elementen im Speicher bleiben, solange irgendwo noch eine Referenz übrig ist.

Außerdem wäre eine Methode, um festzustellen, ob eine Eigenschaft ein Setter ist, auch an anderer Stelle hilfreich, z.B. beim Klonen von Objekten. Damit hatte ich auch so meine Schwierigkeiten...
Mit Zitat antworten
  #6 (permalink)  
Alt 13.12.2014, 00:27
Benutzerbild von protonenbeschleuniger
Verbesserer
XHTMLforum-Kenner
 
Registriert seit: 06.09.2007
Beiträge: 4.977
protonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblick
Standard

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
Jedes Fenster hat ein Objekt/ist ein Objekt. Und nach dem schließen des Fensters soll dieses freigegeben werden. Nun kann man aber an allen möglichen Stellen (das schließt z.B. auch andere IFrames ein) Referenzen auf ein Fensterobjekt speichern und es ist eben nicht ganz einfach, sicherzustellen, dass die alle nach free gelöscht werden.
Wie gesagt genau das macht der GC, er schaut ob eine Referenz noch benötig wird, bevor er etwas frei gibt. Inwiefern verbessert jetzt dein Vorgehen diese Situation? Du weißt doch auch nicht, ob das Frame diesen Zugriff noch braucht?

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
Denn der Zugriff auf ein geschlossenes Fenster ist zum Beispiel möglich (vorgesehen), denn einige Fenster müssen wiederherstellbar sein. Würde ich also auf ein explizites Freigeben verzichten, wäre im Prinzip jedes Fenster wiederherstellbar und würde samt HTML-Elementen im Speicher bleiben, solange irgendwo noch eine Referenz übrig ist.
Das ist die Aufgabe des GC zu entscheiden. Aber wie entschiedest du das?

Und im Prinzip reicht es aus, das Objekt, das die anderen Objekt enthält, auf null zu setzen, damit hat kein anderes Objekt mehr Zugriff auf dieses und alle nicht benötigten Eigenschaften werden auch gelöscht.

Speicherverwaltung ist nichts, womit sich ein JS Programmierer beschäftigen muss.

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
Außerdem wäre eine Methode, um festzustellen, ob eine Eigenschaft ein Setter ist, auch an anderer Stelle hilfreich, z.B. beim Klonen von Objekten. Damit hatte ich auch so meine Schwierigkeiten...
Was meinst du eigentlich mit Setter? Sind das irgendwelche spezielle Methoden bei dir?
Mit Zitat antworten
  #7 (permalink)  
Alt 13.12.2014, 02:27
Erfahrener Benutzer
XHTMLforum-Mitglied
Thread-Ersteller
 
Registriert seit: 09.10.2010
Beiträge: 154
MitjaStachowiak befindet sich auf einem aufstrebenden Ast
Standard

Ich meine so etwas:
Code:
JSWindow.prototype = {
 [...]
 _maximizable : true, get maximizable () { return this._maximizable; }, set maximizable (v) { this._maximizable = v; this.setOrRmAtr(this.el['Buttons'], 'nonmaximizable', !v); },
 [...]
}
Wenn man jetzt schreibt Fenster.maximizable = false; dann wird nicht nur diese Eigenschaft auf false gesetzt, sondern mit setOrRmAtr auch der zugehörige Button ausgeblendet. Und genau hier kommt es zum Fehler, wenn in free dieser Button schon gelöscht wurde.

Ob ein Fenster nach dem schließen freigegeben werden soll, entscheidet die Eigenschaft freeOnHide. In der Regel ist diese true. Wenn nach free noch Referenzen auf das Objekt existieren, sollen diese nicht mehr benutzbar sein.
Zum Beispiel gibt es verschiedene Möglichkeiten, ein Fenster zu erstellen. Das kann zum Beispiel so aussehen:
Code:
 var w = new JSWindow();
 w.maximizable = false;
Dies würde ein leeres Fenster erstellen, das nicht maximierbar ist. Aber angenommen dieser Code steht ungekapselt in einem Iframe eines anderen Fensters (was durchaus realistisch ist, etwa wenn zusammen mit dem letzteren Fenster immer dieses leere Fenster geöffnet werden soll), dann würde die Variable w dafür sorgen, dass das leere Fenster nicht freigegeben werden kann, solange das "Aufrufer-Fenster" geöffnet bleibt. Die Variable w ist dabei auch nicht unbedingt die einzige Referenz. Zum Beispiel können im System-Stadium Fenster über eine ID verfügen. ID-Fenster werden in einer speziellen Liste gespeichert und können nur ein mal (gleichzeitig) geöffnet werden. Natürlich wird das Fenster beim freigeben aus dieser Liste gelöscht (Also ohne free geht es nicht, sonst könnte man danach kein neues Fenster mit dieser ID öffnen), aber angenommen ich habe einen Fehler gemacht und es wird nicht aus der Liste gelöscht - ohne meine spezielle Codezeile, die alle Objekteigenschaften löscht, würde ich diesen Fehler vielleicht nie finden, weil eben kein echter Fehler dadurch entstünde. Nur immer mehr und mehr Speicher.

PS: Übrigens habe ich gerade den von dir verlinkten Text zu Memmory Leaks angesehen und der bestätigt eigentlich nur, was ich immer vermutet habe. Ich behaupte mal, es gibt keine Programmier/Scriptsprache, bei der Garbage Collection so schwierig ist, wie in JavaScript. Allein schon, wann ein Funktionsscope freigegeben werden kann: Wenn die Funktion fertig ist? Nein, Funktionsvariablen können ja auch von EventListenern, die in dieser Funktion gesetzt wurden, aber erst nach deren Beendigung aufgerufen werden, gelesen werden... Und bei meinem Projekt können eben durchaus zyklische Referenzierungen zwischen mehreren Fenstern auftreten, über EventListener, Funktionsscopes, deren Funktion schon beendet ist, und das noch frameübergreifend (und sogar Seitenübergreifend - manche Fenster lassen sich in ein Popup verwandeln, zum Beispiel die Dokumentationsseite zu JS Windows, indem man den Button links neben dem zum minimieren anklickt). Dass das jeder Browser schafft, bezweifele ich. Deswegen kann es nicht schaden, das ganze mit free ein bisschen aufzurütteln...

Geändert von MitjaStachowiak (13.12.2014 um 02:54 Uhr)
Mit Zitat antworten
  #8 (permalink)  
Alt 13.12.2014, 09:41
Benutzerbild von protonenbeschleuniger
Verbesserer
XHTMLforum-Kenner
 
Registriert seit: 06.09.2007
Beiträge: 4.977
protonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblick
Standard

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
PS: Übrigens habe ich gerade den von dir verlinkten Text zu Memmory Leaks angesehen und der bestätigt eigentlich nur, was ich immer vermutet habe. Ich behaupte mal, es gibt keine Programmier/Scriptsprache, bei der Garbage Collection so schwierig ist, wie in JavaScript. Allein schon, wann ein Funktionsscope freigegeben werden kann: Wenn die Funktion fertig ist? Nein, Funktionsvariablen können ja auch von EventListenern, die in dieser Funktion gesetzt wurden, aber erst nach deren Beendigung aufgerufen werden, gelesen werden... Und bei meinem Projekt können eben durchaus zyklische Referenzierungen zwischen mehreren Fenstern auftreten, über EventListener, Funktionsscopes, deren Funktion schon beendet ist, und das noch frameübergreifend (und sogar Seitenübergreifend - manche Fenster lassen sich in ein Popup verwandeln, zum Beispiel die Dokumentationsseite zu JS Windows, indem man den Button links neben dem zum minimieren anklickt). Dass das jeder Browser schafft, bezweifele ich. Deswegen kann es nicht schaden, das ganze mit free ein bisschen aufzurütteln...
Natürlich schadet es, du machst doppelten Aufwand und machst Dinge die der Browser besser macht. Der artikel beschreibt wo die Schwierigkeiten liegen, die du ja nicht besser machen kannst, sondern nur aufwendiger und unzuverlässiger.

Noch mal, das was du beschreibst sind seit Jahrtzehnten die üblichen Aufgaben der GC in Javascript (und anderen dynamischen Sprachen - in Perl sieht die Sache nicht anders aus) und bisher lösen JS Engines diese Aufgabe sehr gut - die einzige Auffällige Ausnahme waren alte Versionen des IEs. Da "von Hand" dran rumschruaben zu wollen ist unötiger Unsinn.
Mit Zitat antworten
  #9 (permalink)  
Alt 13.12.2014, 09:56
Benutzerbild von protonenbeschleuniger
Verbesserer
XHTMLforum-Kenner
 
Registriert seit: 06.09.2007
Beiträge: 4.977
protonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblick
Standard

Zitat:
Zitat von MitjaStachowiak Beitrag anzeigen
Ich meine so etwas:
Code:
JSWindow.prototype = {
 [...]
 _maximizable : true, get maximizable () { return this._maximizable; }, set maximizable (v) { this._maximizable = v; this.setOrRmAtr(this.el['Buttons'], 'nonmaximizable', !v); },
 [...]
}
Wenn man jetzt schreibt Fenster.maximizable = false; dann wird nicht nur diese Eigenschaft auf false gesetzt, sondern mit setOrRmAtr auch der zugehörige Button ausgeblendet. Und genau hier kommt es zum Fehler, wenn in free dieser Button schon gelöscht wurde.
Das ist aber ein ganz spezifisches Problem der Funktion bzw. deines "free" Mechanismus und hat nichts damit zu tun, ob diese Funktion ein setter ist.

Wenn in deinem Code dadurch ein Problem auftaucht, dass du eine öffentliche Eigenschaft änderst, dann darfst du diese nicht öffentlich machen. Das hat aber nichts mit der Speicherverwaltung zu tun.

Wie gesagt, die Browser haben kein Problem mit der Speicherverwaltung, das was du beschreibst klingt eher nach einem Problem in der Logik deiner Anwendung.
Mit Zitat antworten
Sponsored Links
  #10 (permalink)  
Alt 13.12.2014, 10:40
Benutzerbild von protonenbeschleuniger
Verbesserer
XHTMLforum-Kenner
 
Registriert seit: 06.09.2007
Beiträge: 4.977
protonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblickprotonenbeschleuniger ist ein wunderbarer Anblick
Standard

Oder mal ein paar Zitate aus Fachquellen:
Writing Fast, Memory-Efficient JavaScript - Smashing Magazine

Zitat:
It’s not possible to force garbage collection in JavaScript.
D.h. du hast keinen einfluss auf den GC. Das hatte ich bisher vergessen, du markierst lediglich ob ein Wert "aufräumbar" ist, aber das aufräumen an sich kannst du nicht beeinflussen.

Zitat:
n quite a few discussions online about reclaiming memory in JavaScript, the delete keyword is brought up, as although it was supposed to be used for just removing keys from a map, some developers think you can force de-referencing using it. Avoid using delete if you can. In the below example, delete o.x does a lot more harm than good behind the scenes, as it changes o‘s hidden class and makes it a generic slow object.
Wie ich schon sagte, du richtest mehr Schaden und bringt keinen Nutzen.

Und die Tipps sagen es ganz klar, DU musst darauf achten, dass Objekte nicht unötig lange aufbewahrt werden.
Zitat:
To give the garbage collector a chance to collect as many objects as possible as early as possible, don’t hold on to objects you no longer need. This mostly happens automatically;
Du findest dort auch noch Tipps wie du die Geschwindigkeit beim arbeiten mit dem DOM steigern kannst (ein extremer Faktor ist das arbeiten mit DocumentFragement)

und noch mehr:
https://developer.chrome.com/devtool...mory-profiling

Der Punkt ist, um Speicherlöcher zu vermeiden ist es wichtig, den Scope zu löschen, also z.b. die Event- oder Timerfunktion, damit die dort enthaltenen Objekte auch aufgeräumt werden können. Es bringt aber nichts die Objekte selbst zu löschen, solange noch irgendwo Referenzen existieren werden diese nicht von dem GC entfernt.

Oder mal ein Beispiel. Das Element (el) existiert bis zum Schluss, egal ob du es aus dem DOM entfernst oder das Objekt nullst oder die getter Funktion entfernst.
HTML-Code:
      <div id="test">test</div>
    <script type="text/javascript">

var main_f = ( 
function() {
    var el = document.getElementById('test');
    
    function Obj(el){
        this.get = function() { return el;};
        this.toString = function() {
            return el + '';
        };
    }
    
    var o = new Obj(el);

    document.body.removeChild(el);
    el = null;
    
    var ret = (function(x) {
        return function() {
        alert('existiert das Element noch: ' + x);
        alert('aber o.get : ' + x.get);
        };
    })(o);
    
    delete o.get;
    o = null;
    return ret;
    
})();

(function() {
    main_f();

    window.setTimeout(main_f, 1000);
    
})();    
    </script>
Mit Zitat antworten
Sponsored Links
Antwort

Stichwörter
auf setter prüfen, setter erkennen, setter löschen, setter übberschreiben

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Redesign für Steiner Cycling Team pkipper Site- und Layoutcheck 11 09.02.2011 13:25
Prüfen, ob Popup noch existiert xm22 Javascript & Ajax 1 28.06.2010 18:41
Prüfen ob String HTML Code enthält meGa Serveradministration und serverseitige Scripte 3 06.05.2009 17:54
Geerbte Eigenschaft löschen getit CSS 3 27.01.2009 12:04
Eigenschaft einer Klasse selektiv überschreiben subbz2k CSS 12 02.04.2008 16:32


Alle Zeitangaben in WEZ +2. Es ist jetzt 12:33 Uhr.