javascript垃圾收集器没有收集setTimeout()s?

时间:2016-12-21 19:09:42

标签: javascript

我有一个功能:

function test()
{
            for( var i = 0; i < 1000000; i++ )
            {
                setTimeout( function()
                {
                    //
                }, 10000 );
            }
}

在chrome上运行它,它会将内存使用量从大约50MB推进到600MB,我想这是可以的;但是在执行了超时之后,垃圾收集器似乎并没有将它们从内存中删除,它只是保持在600MB直到我刷新,即使这样它仍会留下某种“足迹”#34;页面刷新后为150MB。

知道如何告诉垃圾收集器在执行后将其删除吗?

1 个答案:

答案 0 :(得分:0)

你是对的,似乎有永远不会清理的内存。 我对这个问题的最好猜测是在这样的for循环中创建一个函数会创建一个必须有i访问权限的新范围。因此,这些功能永远不会被清理。我错过了 - 功能一定要清理干净。在我的浏览器中进行测试使内存超过900MB。

重要的是要注意,做你正在做的事情没有任何好处,它最多可归类为“糟糕的代码”。您应该创建一个函数并重用它:

// reusing a function fixes the problem
function test () {
    var fn = function () {};
    for (var i = 0; i < 1000000; i++) {
        setTimeout(fn, 1000);
    }
}

我的观察结果是内存使用量回升超过900MB,然后在几分钟内逐渐回落至接近正常状态。

如果您需要访问函数内部的变量i,我不愿意说您的代码不会提供给您。您只会看到 i(1000000)的最后一个值。如果您想在函数中使用i,可以使用工厂函数。在我的测试中,内存最终得到了清理:

// using a factory fixes the problem and give you access to 'i'
function test () {
    function factory (n) {
        return function () {
            /* This will get called later. 'n' will represent
               the value of 'i' at the time this function was created */
        }
    }
    for (var i = 0; i < 1000000; i++) {
        setTimeout(factory(i), 1000);
    }
};

不幸的是,如果您使用bind

,内存问题仍然存在
// Memory problem still exists with .bind
function test () {
    var fn = function (n) { };
    for (var i = 0; i < 1000000; i++) {
        setTimeout(fn.bind(null, i), 1000);
    }
}

至于页面刷新后内存使用量仍然很高,我无法解释,但它可能与浏览器设置为显示使用大量内存的选项卡留出更多内存。我不知道,只是一个猜测。