关于封锁中的垃圾收集的混淆

时间:2012-05-22 16:44:20

标签: javascript jquery closures

我一直不确定封闭器周围的JS垃圾收集规则,所以我想我也可以问......这是一个很好的例子,我很好奇涉及jQuery的$.each方法:

storeSelection: function() {
    var enabledIds = {};

    $.each(this.nodes, function(index, node) {
        if (node.enabled) {
            enabledIds[ node.id ] = true;
        }
    });

    this.selection = enabledIds;
}

上面的snippit当然是对象字面的一部分。所以,我在外部函数的顶部创建了一个新对象,它将在数组中存储已启用项的ID。使用jQuery的.each()方法,我循环遍历项目数组并记录启用的ID。最后,我将选择存储为父对象的成员。

我的问题涉及从外部范围引用enabledIds对象的内部函数。由于enabledIds会一直存在,这是否会阻止收集内部函数?我不会假设,因为它只是一个在内部函数结束时被清除的变量,对吧?为了成为泄漏,我假设内部函数需要对外部对象进行硬引用,如:

$.each(this.nodes, function(index, node) {
    this.badIdea = enabledIds;
    if (node.enabled) {
        enabledIds[ node.id ] = true;
    }
});

然而......我对这条规则总是模糊不清。任何帮助消除这种困惑都将不胜感激!

2 个答案:

答案 0 :(得分:3)

不,即使你的第二个例子也不足以导致泄密。 badIdea附加到各个节点,$.each块将退出并进行垃圾回收。所有现代浏览器都使用“标记和扫描”算法进行javascript垃圾收集,该算法遵循父对子的关联并收集任何“不可达”,即任何这些树无法访问的内容。

答案 1 :(得分:1)

你是对的,来自内部函数(indexnode)的变量将被垃圾收集,因为它们不再被访问。

在此示例中,您可以访问bigstr吗?

a = function() {
        var bigstr = new Array(1000000).join('x');
        return function() { return bigstr; };
    }();

是的,您可以:a(),因此未收集。这个例子怎么样:

a = function() {
        var bigstr = new Array(1000000).join('x');
        return function(n) { return eval(n); };
    }();

同样,你可以:a('bigstr')

但是这个呢:

a = function() {
        var smallstr = 'x';
        var bigstr = new Array(1000000).join('x');
        return function(n) { return smallstr; };
    }();

你不能再访问它,它是垃圾收集的候选者。