2
var person = {
    name: 'John'
};

function Pet1(person) {
    var owner = person.name;
    this.showOwner = function() {
        alert(owner);
    }
}

function Pet2(person) {
    this.showOwner = function() {
        alert(person.name);
    }
}

var pets = [new Pet1(person), new Pet2(person)];

...

pets.splice(0, 1);
pets.splice(0, 1);

上面的哪个代码阻止了 JS GC 在 Pet1 和 Pet2 超出范围或没有更多引用时不收集它们的实例。我知道的是 Pet2 但你不认为 Pet1 也能阻止 JS GC 吗?

4

2 回答 2

1

关于您评论中的问题:

人(在这种情况下是全局的)变量是否会阻止 Pet1 和 Pet2 的实例被垃圾收集(如果超出范围并且没有更多引用)

不,为什么要这样?person不引用 Pet 实例,反之亦然。一旦您从数组中删除了对 Pet 实例的引用pets,就没有什么可以阻止 GC 收集它们(假设您的 " ..." 代码不会创建对pets[0]or的其他引用pets[1])。

于 2013-03-16T15:06:08.723 回答
0

答案是“视情况而定”。

就现代引擎而言,如果person从系统中的其他任何地方删除它,它仍然可以被收集,即使它在论点中被提及,因为尽管它在闭包内,但它再也不会从任何公开的方法中被引用可用的。

因此,支持删除范围的残留部分的引擎可以轻松地在该对象上运行 GC。

那么,问题是哪些引擎可以做到这一点,以及这些引擎的哪些版本可以做到这一点?
我不确定这个问题的答案。

只是它是可能的,但可以在旧的或较小的 JS 引擎上保持驻留在内存中。

编辑

可以这样想:var pet1 = new Pet1(person); Pet1 使用 person 为 pet1 设置值。
人们对pet1一无所知。

var pet2 = new Pet2(person);
pet2 具有查找人员的功能,以读取值。
因此,即使代码中再也没有提到人员,也无法将其删除,因为 pet2 可能会调用需要查找人员的函数……
人员仍然不知道 pet2 是什么。

当 pet2 不再需要时,当它从上面的数组中删除时,当每个引用它的单个变量/对象属性/数组索引都删除其引用时,包括删除在它的作用域内创建的函数存在于其中并且有对其的引用,不知何故,它可以被删除,因为没有其他代码正在寻找/挂在pet2上。

一旦 pet2 消失,person 就不再用于其他任何地方。
因此,可以标记人员以供收集。

GC 就是关于什么可以访问一个东西。
如果其他事情还在谈论对象,那么该对象是不允许被移除的。
一个实例可能依赖于 50 个参数,并引用了 120 个其他外部对象,但如果没有其他人关心,该实例仍然可以被收集。

于 2013-03-16T07:51:31.430 回答