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

IT技术 javascript ajax browser memory-leaks
2021-02-24 03:01:14

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

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

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

6个回答

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

(这是相当现成的。)

在当前最先进的浏览器状态中,内存使用确实是一个您需要关注的问题,尽管除非我们谈论相当多的代码,否则我不知道代码大小是问题(通常是 DOM 大小) ,以及剩余的事件处理程序)。

你可以为你的可加载module使用一个模式,这样可以更容易地卸载它们——或者至少,让浏览器知道它可以卸载它们。

考虑:

window.MyModule = (function() {

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

    function MyModule() {

        function foo() {
            bar();
        }

        function bar() {
        }

    }

    return MyModule;
})();

这定义了一个包含函数fooand的闭包bar,它们可以以正常方式相互调用。请注意,函数外的代码会立即运行。

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

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

这会告诉 JavaScript 环境您不再使用该属性,并使其引用的任何内容都可用于垃圾收集。该收集何时以及是否发生显然取决于实现。

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

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;
})();

脱钩是:

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;
    }
}

如果将评估的代码保存在命名空间中,例如:

var MYAPP = {
    myFunc: function(a) { ... }
}

“释放”整个事情应该像将 MYPP 设置为某个随机值一样简单,唉

MYAPP = 1

这确实取决于没有其他引用变量的方法,这不是微不足道的

为什么不删除 MYAPP 或 MYAPP = undefined?
2021-04-26 03:01:14
@txwinker:是的,我想我觉得这是暗示。要使其正常工作,不得引用 MYAPP 或其中的任何内容。当涉及到内存泄漏和 IE 时,还有一些挑剔的细节。@Dykam:没有理由不去定义,但我避免删除,因为我没有很多经验,并且“1”不应该给 OP 可能正在做的任何事情带来巨大的内存压力。
2021-05-02 03:01:14
不仅是变量本身,还有可能创建的任何闭包是内部函数。
2021-05-09 03:01:14

如何将 JS 文件加载到 iframe 中?然后(理论上,我自己从未测试过)您可以从 DOM 中删除 iframe 并删除它正在使用的“内存”。

我想……或者我希望……

如果您担心内存泄漏,那么您需要确保在要删除的代码中没有引用仍然存在的 dom 树的事件处理程序。

您可能需要保留您的代码添加的所有事件处理程序的列表,并且在卸载之前,检查并删除事件处理程序。

我从来没有这样做过,我总是担心删除节点时仍然存在引用。

这是一篇关于 javascript 内存泄漏的好文章:http : //javascript.crockford.com/memory/leak.html