2010-12-06 5 views
17

Wie kann ich eine JavaScript-Ressource mit allen definierten Objekten aus dem DOM entfernen?Wie man ein Javascript von einem HTML löscht?

Ich entwickle ein einfaches Framework, das HTML-Fragmente in einen "Haupt" -Html laden kann. Jedes Fragment ist eigenständig und kann Verweise auf zusätzliche JS- und CSS-Dateien enthalten. Die JS- und CSS-Ressourcen werden analysiert und dem HTML dynamisch hinzugefügt. Wenn das Fragment aus dem DOM entfernt/ersetzt wird, möchte ich JS und CSS entfernen.

Wenn ich das Skriptelement im folgenden Beispiel entferne, sind die in page1.js definierten Funktionen weiterhin verfügbar.

<html> 
    <head> 
    <script src="page1.js" type="text/javascript"></script> 
    </head> 
<body> 
... 

Gibt es eine Möglichkeit, page1.js Objekte aus dem DOM zu entladen?

========= Der Testcode Ich benutze =======

ich den Rat habe ich versucht, in den Kommentaren unten bekam; Löschen der hinzugefügten Objekte mit einer Bereinigungsfunktion - aber selbst dies schlägt fehl. Die Quellen i für den Test verwendet:

<html> 
<head> 
<script type="text/javascript"> 
    function loadJSFile(){ 
     var scriptTag = document.createElement("script"); 
     scriptTag.setAttribute("type", "text/javascript"); 
     scriptTag.setAttribute("src", "simple.js"); 

     var head = document.getElementsByTagName("head")[0]; 
     head.appendChild(scriptTag); 
    } 

    function unloadJSFile(){    
     delete window.foo; 
     delete window.cleanup; 
     alert("cleanedup. typeof window.foo is " + (typeof window.foo)); 
    } 
</script> 
</head> 
<body> 

    Hello JavaScript Delete 

    <br/> 
    <button onclick="loadJSFile();">Click to load JS</button> 
    <br/> 
    <button onclick="foo();">call foo()</button> 
    <br/> 
    <button onclick="unloadJSFile();">Click to unload JS</button> 

</body> 
</html> 

simple.js Quelle:

var foo = function(){ 
    alert("hello from foo"); 
} 
+0

Wenn Sie es in einer objektiven Weise betrachten, versuchen Sie, dasselbe wie in zu tun: http://stackoverflow.com/questions/3830133/avoiding-pollution-of-globals-via-iframe-script -loader/3882324 # 3882324. . iframes scheinen ein ziemlich normaler Weg zu sein, so viel wie möglich in Bezug auf die Bereinigung zu tun. –

+0

@Ravindra: Ich kann nicht iFrames verwenden, weil ich nicht weiß, was die Dimension des Fragments ist, außerdem muss das Fragment mit dem vorhandenen Code auf der Seite kommunizieren. – Totach

+0

Wird die Ressource JS von Ihnen gepflegt? Wenn ja, wird ein wenig Architektur um das JS sicherlich hilfreich sein. Die Antworten unten von cdhowie und schwer zu helfen wäre –

Antwort

4

vielleicht müssen Sie bedingt es eher als bedingt es Laden betrachten Entladen ...

6

Nein, das ist nicht möglich. Sie könnten eine einfache Funktion erstellen, die alle Variablen entfernt, die in dieser Datei definiert wurden:

var foo = 'bar'; 
var cleanup = function() { 
    delete window.foo; 
    delete window.cleanup; 
}; 

// unload all resources 
cleanup(); 

Ein anderer Ansatz eine modulare Objektstruktur für Ihre Fragmente zu verwenden wäre, die nach selbst aufzuräumen. Das beinhaltet einen etwas höheren Aufwand, ist aber wahrscheinlich lohnt sich, wie es der Code viel leichter zu lesen und zu pflegen macht:

// creates the object using the second parameter as prototype. 
// .create() is used as constructor 
GlobalModuleHandlerThingy.addModule('my_module', { 
    create: function() { 
     this.foo = 'bar'; 
     return this; 
    }, 
    foo: null, 
    destroy: function() { 
     // unload events, etc. 
    } 
}); 

GlobalModuleHandlerThingy.getModule('my_module').foo; // => bar 
GlobalModuleHandlerThingy.unloadModule('my_module'); // calls .destroy() on the module and removes it. 
+1

Möglich, aber erforderlich, um die Bereinigung manuell zu definieren und Speicherlecks zu verursachen. Ich brauche diese Lösung für ein einfaches Framework im Schreiben, die es einem einzelnen HTML ermöglicht, HTML-Fragmente dynamisch zu laden, die mit zusätzlichen JS- und CSS-Ressourcen verknüpft sind. Wenn Fragmente ersetzt werden, muss ich ihren JS- und CSS-Kontext entladen. – Totach

+0

@Totach: Richtig, aber das ist die einzige Möglichkeit, sich von diesen Variablen zu befreien. Das Entfernen von Ereignissen usw. muss dabei berücksichtigt werden. Dies ist nur ein einfaches Beispiel. – jwueller

+0

Ich habe deine Lösung aus irgendeinem seltsamen Grund versucht - die Objekte können nicht gelöscht werden !? (false wird in Firefox zurückgegeben). Beachten Sie, dass das Skript dynamisch geladen wird, indem Sie ein Skript-Tag erstellen. Irgendeine Idee? Danke vielmals! – Totach

13

Dies kann nicht getan werden.

Wenn ein Skript ausgeführt wird, werden Funktionsdefinitionen zum globalen Objekt window hinzugefügt. Es können Debugging-Symbole an die Funktion angehängt sein, die angeben, woher die Funktion stammt, aber diese Informationen sind für Skripts nicht verfügbar.

Über die einzige Möglichkeit, wie Sie etwas erreichen könnten, wäre ein Pseudonamespace im Skript zu erstellen und dann den gesamten Namespace wegzuwerfen, wenn Sie damit fertig sind. Diese Frage deutet jedoch darauf hin, dass Sie versuchen, etwas falsch zu machen. Vielleicht hilft uns die Ausarbeitung Ihres Szenarios, alternative Lösungen anzubieten.

+1

Danke - das Hinzufügen der Objekte zu einem Namespace und das anschließende Löschen scheint der beste Ansatz zu sein. – Totach

+1

@Totach: Die Speicher-Lecks sind immer noch ein Problem bei der Verwendung dieses Ansatzes, aber Sie haben sich wahrscheinlich schon darum gekümmert. – jwueller

1

Wenn Sie ein bestimmtes Objekt entladen müssen, es ist ziemlich einfach: legen Sie es nur zu {}

dh: myobj = {};

Also, wenn Sie wissen, welche Objekte erstellt werden in einem bestimmten umfasst, wird es nicht sei überhaupt schwer.

Wenn Sie andererseits nicht wissen, welche Objekte in einem bestimmten Include erstellt werden, gibt es keinen Mechanismus, den Sie herausfinden können. Sie können Javascript nicht anfordern, um zu erfahren, was in einem bestimmten Include definiert wurde .

Allerdings würde ich sagen, wenn Sie nicht wissen, welche Objekte in einer bestimmten Javascript-Datei geladen werden, tun Sie sich wahrscheinlich keine Gefälligkeiten beim Laden (Sie sollten immer eine vernünftige Idee haben, was Code tut auf Ihrer Website) oder beim manuellen Entladen versuchen (wenn Sie nicht wissen, was es tut, bedeutet dies, dass es ein Drittanbieter-Include ist, was bedeutet, dass das manuelle Aufheben des Scripts wahrscheinlich zu Problemen führt).

+0

könnte es auch mit Funktionen gemacht werden: 'function name() = {}' – jechaviz

0

für etwas erforschte wie das mich und dachte, ich werde meine Erkenntnisse

  1. Wickeln Sie Ihre Sachen in einem globalen Namensraum in js Datei veröffentlichen, damit es leicht entfernt werden kann, das heißt var Zeug = {blabla : 1, Methode: function() {}};

  2. Wenn Sie es loswerden müssen, geben Sie einfach Sachen = {}, oder null, selbst

  3. Remove Script-Tag ab Seite

*** Wenn Sie requirejs verwenden - require js remove definition to force reload

Hinweis: Solange Sie keine Module innerhalb des Namespace von irgendwo anders referenzieren, wird alles von GC erfasst und Sie können loslegen.

0

Ich habe einen Trick dafür gefunden. Ich habe mich schon einige Tage gefragt, ob ich eine Antwort dafür finden könnte und ich habe einfach einen perfekten Trick dafür gefunden, ohne zu versuchen, das Java Script zu löschen. Sie müssen nur eine globale Variable wie currentPage in Ihrem Java Script java main erstellen und beim Laden der Seite den Seitennamen currentPage zuweisen. dann in jeder anderen .js Datei verwenden $('document').ajaxComplete() statt $('document').ready() fügen Sie eine if-Anweisung als erste Zeile innerhalb jeder $('document').ajaxComplete() Funktion. Stellen Sie es so ein, dass currentPage Variable mit einem neuen Seitennamen übereinstimmt. füge alle anderen Ereignisse in die if-Anweisung ein. Ich kann kein Englisch, also überprüfe meinen Code. und dies ist meine erste Antwort hier so leid, wenn ich ein paar Fehler mache.

main.html

<body> 
    <div id='container></div> 
    <button id="load1"> 
    <button id="load1"> 
</body> 

main.js

var currentPage = ""; 

$(document).ready(function() { 
    $('#load1').click(function() { 
     loadSource('page1', 'body'); 
    }); 
    $('#load2').click(function() { 
     loadSource('page2', 'body'); 
    }); 
}); 

function loadSource(page, element){ 
    currentPage = page; 
    $('#container').load('views/' + page + '.php', element); 
    $.getScript('js/' + page + '.js'); 
    $('#css').prop('disabled', true).remove(); 
    $('head').append('<link rel="stylesheet" href="css/' + page + '.css" type="text/css" />'); 
} 

sind alle meine Seiten Skripte und Stile in separaten Ordnern Ansichten, js, css.

page1.html

<body> 
    <button id="test1"> 
    <button id="test2"> 
</body> 

page1.js

$(document).ajaxComplete(function() { 
    if(currentPage == 'page1'){ 
     /*$('#test1').click(function() { 
      console.log('page1'); 
     });*/ 
     $('#test2').click(function() { 
      console.log('page1'); 
     }); 
    } 
}); 

page2.html

<body> 
    <button id="test1"> 
    <button id="test2"> 
</body> 

page2.js

$(document).ajaxComplete(function() { 
    if(currentPage == 'page2'){ 
     $('#test1').click(function() { 
      console.log('page2'); 
     }); 
     /*$('#test2').click(function() { 
      console.log('page2'); 
     });*/ 
    } 
}); 

Ich habe in jedem Skript eine Schaltfläche kommentiert, um zu überprüfen, ob diese Schaltfläche noch Auswirkungen auf das alte Skript hat.

Verwandte Themen