用javascript标记和扫描(上下文变量)

时间:2012-11-03 12:15:57

标签: javascript garbage-collection

我正在阅读面向网络开发人员的专业JavaScript

我在阅读时遇到问题“当垃圾收集器运行时,它会标记存储在内存中的所有变量。然后清除上下文中的变量引用的变量的标记通过上下文变量。“

我知道当任何变量无法访问对象时,将回收相关的内存。

“上下文中的变量”是什么意思?它们是可以在范围链中找到的变量吗?但是“上下文变量引用的变量”呢?

我很困惑。

2 个答案:

答案 0 :(得分:2)

我假设是为了避免意外删除闭包中使用的变量。在javascript中,就像任何其他功能语言一样,只是无法访问并不足以告诉你应该删除对象的天气。

以下面的代码为例:

function a () {
    var x=0;
    return function () {
        alert(x++);
    }
}

var b = a();
// at this point, the instance of `x` created by calling `a` is
// no longer reachable but we are still using it in the closure.

如果我们只遵循“不可达性”规则,那么创建的闭包将失去变量x

答案 1 :(得分:0)

考虑一下:

(function(){
    var sobriety = [];
    window.inception = function() {
        var i = 0, 
            j = 0,
            inner_level = { i: i }, 
            level       = { level: inner_level },
            food        = {};
        return function() { 
            var new_level = {
                level: level.level
            };
            new_level[i] = 'step ' + i;
            new_level.level.i = i;
            sobriety[i++] = new_level; 
        };
    };
    window.show_my_sobriety = function() { console.log(sobriety); };
})();

var agent = inception();
agent(); agent(); agent();
show_my_sobriety();​

JS Fiddle

我承认这个例子有些复杂,但我只需要让它显示i(一个原始)和inner_level(一个引用类型)之间的区别。

这里我们有一个模块,其中一个sobriety变量是局部的,两个函数是全局的(通过将它们分配给window对象的属性)。请注意,即使已完成定义的模块(sobriety),这些全局函数也可以访问in-context变量。

inception函数在调用时定义了五个变量:两个标量(ij)和三个引用(inner_levellevel和{{ 1}}),然后定义一个函数并返回它。

此功能显然可以访问foodi(相同的上下文)和level(外层上下文) - 但不是sobrietyj 。因此,在food完成后,GC将立即收集后者;然而,前者仍未被收集 - 因为它们被内部功能所引用。

现在是棘手的部分。虽然您在此函数中看不到window.inception的访问权限,但仍然可以访问它 - 因为它是同名对象的inner_level属性值。并且,当您检查结果时,您会看到所有三个元素都具有相同的level值 - 等于2.这就是“由上下文变量引用的变量”所理解的内容。