可以卸载动态加载的JavaScript吗?

And*_*ndy 12 javascript browser ajax memory-leaks

我正在编写一个具有静态外部"shell"和动态内容部分的Web应用程序.当用户导航系统时,动态内容部分有许多更新.加载新内容块时,它还可以选择加载另一个JavaScript文件.在良好的内务管理的名义下,我从DOM中删除适用于旧内容块的脚本块,因为不再需要JavaScript.

接下来出现问题,当我意识到虽然我已经<script>从DOM中删除了元素,但之前评估的JavaScript仍然可以执行.这当然有道理,但我担心如果用户导航到很多不同的部分,它可能会导致内存泄漏.

那么问题是,我应该担心这种情况吗?如果是这样,有没有办法强制浏览器清理过时的JavaScript?

Sam*_*son 14

<theory>您可以采用更加面向对象的方法,并以每个javascript块块作为自己的对象,使用自己的方法构建模型.在卸载它时,您只需将该对象设置为null.</theory>


T.J*_*der 9

(这是相当缺乏的.)

内存使用确实是一个你需要关注的问题,在当前的浏览器技术水平,虽然除非我们谈论相当多的代码,我不知道代码大小是问题(它通常是DOM大小和剩下的事件处理程序).

您可以使用可加载模块的模式,这样可以更容易地将它们大量卸载 - 或者至少让浏览器知道它可以卸载它们.

考虑:

window.MyModule = (function() {

    alert('This happens the moment the module is loaded.');

    function MyModule() {

        function foo() {
            bar();
        }

        function bar() {
        }

    }

    return MyModule;
})();
Run Code Online (Sandbox Code Playgroud)

这定义了包含功能的闭合foobar,其可以相互调用以正常方式.请注意,函数外部的代码会立即运行

如果你没有将对闭包内部内容的任何引用传递给它之外的任何东西,那么window.MyModule将是对该闭包及其执行上下文的唯一引用.要卸载它:

try {
    delete window.MyModule;
}
catch (e) {
    // Work around IE bug that doesn't allow `delete` on `window` properties
    window.MyModule = undefined;
}
Run Code Online (Sandbox Code Playgroud)

这告诉JavaScript环境你不再使用该属性,并使其引用的任何内容可用于垃圾收集.何时以及是否发生该集合显然是依赖于实现的.

请注意,如果您在模块中挂钩事件处理程序以在卸载之前取消挂钩它们将非常重要.你可以通过返回对析构函数的引用而不是主闭包来做到这一点:

window.MyModule = (function() {

    alert('This happens the moment the module is loaded.');

    function foo() {
        bar();
    }

    function bar() {
    }

    function destructor() {
        // Unhook event handlers here
    }

    return destructor;
})();
Run Code Online (Sandbox Code Playgroud)

然后解开:

if (window.MyModule) {
    try {
        window.MyModule();
    }
    catch (e) {
    }
    try {
        delete window.MyModule;
    }
    catch (e) {
        // Work around IE bug that doesn't allow `delete` on `window` properties
        window.MyModule = undefined;
    }
}
Run Code Online (Sandbox Code Playgroud)