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吗?

最佳答案

答案是“取决于”。

就现代引擎而言,如果将person从系统中的其他任何地方删除,即使在参数中提到了它,也仍可以将其收集起来,因为尽管它位于闭包内部,但从未使用任何方法再次引用过这是公开可用的。

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

那么问题是,哪些引擎可以执行此操作,以及这些引擎的哪些版本可以执行此操作?
我不确定答案。

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

编辑

这样想:var pet1 = new Pet1(person);
Pet1使用人员来设置pet1的值。
人对pet1一无所知。

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

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

一旦pet2消失了,就不再在其他任何地方使用人了。
因此,可以将人标记为要收集。

GC就是关于事物可以访问的内容。
如果其他事情仍在讨论该对象,则不允许删除该对象。
一个实例可能依赖于50个参数,并引用了120个其他外部对象,但是如果没有其他人关心它,则仍然可以收集该实例。

09-25 16:16