如何从HTML中卸载JavaScript?

时间:2010-12-06 09:47:44

标签: javascript dom

如何从DOM中卸载包含其所有已定义对象的JavaScript资源?

我开发了一个简单的框架,可以将html片段加载到“主”html中。每个片段都是自包含的,可能包含对其他JS和CSS文件的引用。解析JS和CSS资源并将其动态添加到html中。当从DOM中删除/替换片段时,我想删除它的JS和CSS。

如果我删除了下面示例中的script元素,则page1.js中定义的函数仍然可用。

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

有没有办法从DOM中卸载page1.js对象?

=========我使用的测试代码=======

我尝试了下面评论中的建议;使用清理功能删除添加的对象 - 但即使这样也会失败。我用来测试的来源:

<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来源:

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

7 个答案:

答案 0 :(得分:14)

这不可能。

执行脚本时,函数定义将添加到全局window对象中。可能存在附加到函数的调试符号,用于指示函数的来源,但脚本无法使用此信息。

关于实现这样的事情的唯一方法是在脚本中创建一个伪命名空间,然后在完成后抛弃整个命名空间。但是,这个问题告诉我你正试图以错误的方式做某事。也许详细说明你的场景将有助于我们提供替代解决方案。

答案 1 :(得分:6)

不,那是不可能的。您可以构建一个简单的清理函数,删除该文件中定义的所有变量:

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

// unload all resources
cleanup();

另一种方法是为片段使用模块化对象结构,然后自行清理。这涉及稍高的开销,但可能是值得的,因为它使代码更容易阅读和维护:

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

答案 2 :(得分:4)

也许您需要考虑有条件地加载它而不是有条件地卸载它......

答案 3 :(得分:2)

如果您需要卸载特定对象,则相当简单:只需将其设置为{}

ie:myobj = {};

因此,如果您知道在特定包含中创建了哪些对象,那么它就不会很难。

另一方面,如果您不知道在特定包含中创建了哪些对象,则无法找到机制 - 您不能要求Javascript告诉您在特定包含中定义了什么。

但是,我会说,如果你不知道在特定的javascript文件中加载了什么对象,你可能不会在加载它时给自己任何好处(你应该总是有一个合理的想法,代码在做什么)你的网站),或试图手动卸载它(如果你不知道它做了什么,这意味着它的第三方包括,这意味着手动取消它可能会破坏它。)

答案 4 :(得分:0)

我正在研究类似的事情并认为我会发布我的发现

  1. 将您的东西包装在js文件中的全局命名空间中,以便可以轻松删除它,即 var stuff = {blabla:1,method:function(){}};

  2. 当你需要摆脱它时,只需设置stuff = {},或者甚至是

  3. 从页面中删除脚本标记
  4. ***如果您使用requirejs - require js remove definition to force reload

    注意:只要您不在其他任何地方引用命名空间内的模块,GC就会收集所有内容,您就可以开始使用了。

答案 5 :(得分:0)

  

我想到了这个诀窍。我想知道这里几天找到答案,我只是意识到一个完美的技巧,而不试图卸载Java脚本。您只需要在currentPage页面的java脚本中创建一个全局变量,如main,当您加载页面时,将页面名称指定给currentPage。然后在每个其他.js文件中使用$('document').ajaxComplete() $('document').ready() {}} {}} {}} {}} {}} {{}}将其设置为检查$('document').ajaxComplete()变量等于新的页面名称。在if语句中添加所有其他事件。我不太懂英语所以请检查我的代码。这是我的第一个答案,如果我犯了一些错误就很抱歉。

main.html中

currentPage

main.js

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

我的所有页面脚本和样式都在单独的文件夹视图中,js,css。

page1.html

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

page1.js

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

page2.html

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

page2.js

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

我在每个脚本中注释了一个按钮,以检查该按钮是否仍然具有旧脚本的影响。

答案 6 :(得分:0)

您可以将它们设置为null

    function fnc1 (){

    }

    window.fnc1  = null
    //or
    window["fnc1"]  = null