2010-12-06 29 views
17

¿Cómo puedo descargar un recurso de JavaScript con todos sus objetos definidos desde el DOM?¿Cómo descargar un javascript de un html?

Im desarrollando un marco simple que permite cargar fragmentos html en un html "principal". Cada fragmento es independiente y puede incluir referencias a archivos JS y CSS adicionales. Los recursos JS y CSS se analizan y se agregan dinámicamente al html. Cuando el fragmento se elimina/reemplaza del DOM, quiero eliminar su JS y CSS.

Si elimino el elemento script en el ejemplo a continuación, las funciones definidas en page1.js todavía están disponibles.

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

¿Hay alguna manera de descargar objetos de page1.js del DOM?

========= El código de prueba que uso =======

Probé el consejo que me dieron en los comentarios; para eliminar los objetos agregados usando una función de limpieza, pero incluso esto falla. Las fuentes que he usado para las pruebas:

<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 fuente:

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

Si lo ves de manera objetiva, estás tratando de hacer lo mismo que en: http://stackoverflow.com/questions/3830133/avoiding-pollution-of-globals-via-iframe-script -loader/3882324 # 3882324. . iframes parece ser una forma bastante normal de hacer todo lo posible con respecto a la limpieza. –

+0

@Ravindra: No puedo usar iFrames porque no sé cuál es la dimensión del fragmento, además, el fragmento necesita comunicarse con el código existente en la página. – Totach

+0

¿Mantiene usted el recurso JS? En caso afirmativo, un poco de arquitectura en torno a la JS seguramente será de ayuda. Las respuestas a continuación por cdhowie y escurridizas serían de ayuda –

Respuesta

4

quizá debe tener en cuenta de forma condicional de cargarlo de forma condicional en lugar de descargarlo ...

6

No, eso es imposible. Se puede construir una función de limpieza simple que elimina todas las variables que se definieron en ese archivo:

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

// unload all resources 
cleanup(); 

Otro enfoque sería el uso de una estructura modular objeto de sus fragmentos, que limpiar ellos mismos. Esto implica una sobrecarga ligeramente superior, pero es probable que vale la pena, ya que hace que el código mucho más fácil de leer y mantener:

// 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

Posible pero requiere definir la limpieza manualmente y puede provocar pérdidas de memoria. Necesito esta solución para un simple framework im writing que permite que un html único cargue dinámicamente fragmentos html que enlazan a recursos adicionales de JS y CSS. Cuando los fragmentos son reemplazados, necesito descargar su contexto JS y CSS. – Totach

+0

@Tachach: Correcto, pero esta es la única forma de librarse de esas variables. Separación de eventos, etc. debe tenerse en cuenta al hacerlo así. Este es solo un simple ejemplo. – jwueller

+0

Intenté su solución, pero por alguna extraña razón, ¡los objetos no se pueden eliminar !? (falso se devuelve en firefox). Tenga en cuenta que el script se carga dinámicamente creando una etiqueta de script. ¿Alguna idea? ¡muchas gracias! – Totach

13

Esto no se puede hacer.

Cuando se ejecuta un script, las definiciones de funciones se agregan al objeto global window. Puede haber símbolos de depuración adjuntos a la función que indiquen de dónde vino la función, pero esta información no está disponible para los scripts.

Acerca de la única forma en que podría lograr algo como esto sería crear un pseudo-espacio de nombres en el script y luego descartar ese espacio de nombre completo cuando haya terminado con él. Sin embargo, esta pregunta me sugiere que estás tratando de hacer algo de la manera incorrecta. Tal vez la elaboración de su escenario nos ayude a proporcionar soluciones alternativas.

+1

Gracias: agregar los objetos a un espacio de nombre y luego eliminarlo parece ser el mejor enfoque. – Totach

+1

@Tachach: Las fugas de memoria siguen siendo un problema cuando se usa este enfoque, pero probablemente ya se haya ocupado de eso. – jwueller

1

Si necesita descargar un objeto específico, que es bastante fácil: simplemente lo puso a {}

es decir: myobj = {};

Así que si usted sabe qué objetos son creados en un determinado incluyen, no lo hará ser duro en absoluto.

Por otro lado, si no sabes qué objetos se crean en una inclusión particular, no hay un mechansim para averiguarlo; no puedes pedirle a Javascript que te diga qué se definió en una inclusión particular .

Sin embargo, yo diría que si no sabe qué objetos se están cargando en un archivo javascript en particular, probablemente no se esté haciendo ningún favor al cargarlo (siempre debe tener una idea razonable de qué código hace en su sitio), o al tratar de descargarlo manualmente (si no sabe lo que hace, eso implica que se incluya un tercero, lo que significa que es posible que deshacerlo manualmente pueda romper las cosas).

+0

se podría hacer también con funciones: 'function name() = {}' – jechaviz

0

estaba investigando para algo así como que yo y pensé voy a publicar mis resultados

  1. envolver su materia en un espacio de nombres global en js por lo que se puede quitar fácilmente, es decir cosas var = {blabla : 1, método: function() {}};

  2. Cuando tenga que deshacerse de él, las cosas simplemente establecer = {}, o incluso nula

  3. etiqueta Eliminar el guión de la página

*** Si utiliza RequireJS - require js remove definition to force reload

Nota: siempre que no haga referencia a los módulos dentro del espacio de nombres desde cualquier otro lugar, GC recopilará todo y estará listo.

0

Me pareció un truco para esto. Me estaba preguntando por aquí días encontrar una respuesta para esto y me acabo de dar cuenta de un truco perfecto para hacer esto sin intentar descargar el script java. lo único que debe hacer es crear una variable global como currentPage en el script java de su página main y cuando cargue la página asigne el nombre de la página al currentPage. luego en cualquier otro archivo .js use $('document').ajaxComplete() insted de $('document').ready() agregue una instrucción if como primera línea dentro de cada función $('document').ajaxComplete(). establézcalo para verificar currentPage variable es igual a un nuevo nombre de página. agregue todos los demás eventos dentro de la instrucción if. no sé inglés muy bien, así que revisa mi código. y Esta es mi primera respuesta aquí, así que lo siento si cometo algunos errores.

principal.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" />'); 
} 

todas las páginas de mis guiones y estilos están en las vistas de carpetas separadas, 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'); 
     });*/ 
    } 
}); 

comenté un botón en cada secuencia de comandos para comprobar si ese botón todavía tiene el efecto de la secuencia de comandos anterior.

Cuestiones relacionadas