【问题标题】:How does this js code leak memory?这个js代码是怎么泄露内存的?
【发布时间】:2016-11-17 09:42:02
【问题描述】:

我一直在阅读有关 js 最佳实践和常见错误的信息,我从https://www.toptal.com/javascript/10-most-common-javascript-mistakes 看到了这段代码

var theThing = null;
var replaceThing = function () {
    var priorThing = theThing;  // hold on to the prior thing
    var unused = function () {
        // 'unused' is the only place where 'priorThing' is referenced,
        // but 'unused' never gets invoked
        if (priorThing) {
            console.log("hi");
        }
    };
    theThing = {
        longStr: new Array(1000000).join('*'),  // create a 1MB object
        someMethod: function () {
            console.log(someMessage);
        }
    };
};

我尝试将此代码输入控制台并多次调用replaceThing(),确实如此,即使在 GC 之后,Chrome 任务管理器中的内存使用量也会上升。

闭包unused 保留对priorThing 的引用,从而使其不符合GC 条件。但是:

  1. priorThing = theThing 执行时,unused 闭包中的引用是否也更改为theThing
  2. 即使 #1 不是这种情况,当 replaceThing 的执行完成时,变量 unused 是否应该超出范围?

【问题讨论】:

    标签: javascript memory-leaks garbage-collection


    【解决方案1】:

    是的,存在内存泄漏。这是因为在 Javascript 中实现闭包的方式。每个函数对象都有一个指向表示其词法范围的字典样式对象的链接。 IF A VARIABLE IS USED IN ONE CLOSURE, IT ENDS UP IN THE LEXICAL SCOPE SHARED BY ALL OTHER CLOSURES IN THAT SCOPE。在这种情况下,我们在同一范围内有两个闭包 theThingunused。在unused 中使用priorThing,现在priorThing 是闭包中的变量,就像unused 没有被调用一样,意味着priorThing 也在theThing 闭包的范围内。所以priorThingreplaceThing 返回后不会被垃圾收集。

    1) 当priorThing = theThing被执行时,旧的theThing值被存储到priorThing,所以unused指的是旧的theThing而不是新创建的

    【讨论】:

    • 我尝试在控制台中查看函数范围。我的理解是否正确:当创建 theThing 中的 someMethod 闭包时,它会保留对未使用的引用,而未使用的引用本身会保留对priorThing 的引用。 priorThing 本身包含了之前版本的 someMethod,并且对之前版本的未使用,形成了指向第一个对象的引用链?
    • “如果一个变量在一个闭包中使用,它最终会出现在该范围内所有其他闭包共享的词汇范围内”你能给我一个链接吗?我想了解更多有关它的信息
    • 你会在那里得到一个非常详细的解释。如果你不明白,请联系我
    猜你喜欢
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多