是否有必要取消垃圾收集的原始值?

Is it necessary to nullify primitive values for grabage collection?

如果我有以下代码:

function MyClass() {
    this.data = {
        // lots of data
    };
}

var myClassInstace = new MyClass();

var myobj = {
    num:123,
    str:"hello",
    theClass:myClassInstance
};

我知道这是绝对必要的:

myobj.theClass = null;

为 GC 释放 myClassInstance 及其 data 属性。但是,myobj.nummyobj.str该怎么办呢?我也必须给他们 null 的值吗?它们是原始的这一事实是否会改变有关 GC 的任何内容?

设置为 undefined(不为空)将起作用,但是 delete 是更好的示例 delete myobj.theClass

为了避免误解,我会说在 JavaScript 中没有办法真正从内存中删除对象。您删除它的引用或将它们设置为未定义,以便 GC 可以完成它的工作并真正删除。

有很多 "it depends here",从您的代码正在做什么到您使用的浏览器 运行。但是,如果您的对象是 JIT 编译的,则不使用映射它的属性,那么数字应该是一个 8 字节的双精度内联存储在对象中。将其置零将无济于事。

字符串和 myclass 实例将是指向对象外部分配的内存的指针(由于字符串可以是任意多字节,它不能存储在对象内部。编译器可以想象存储一个实例内存中的字符串,永远不要释放它)。将它们置空可以让垃圾收集器在主对象超出范围之前释放它们。

然而,真正的问题是你为什么担心这个。除非您分析了您的代码并将垃圾收集或内存泄漏确定为问题,否则您不应该尝试优化 GC 行为。特别是,除非您的 myobj 对象本身将长期存在,否则您不应该担心清零字段。当它超出范围时,GC 将收集它。

实现垃圾收集的 JavaScript 运行时将能够在无法从代码中访问值时立即收集项目。对于对象引用和基元都是如此。收集项目的确切时刻的细节因实现而异,但甚至没有必要将对象引用设置为 null(如您所述),除非您需要在当前函数自然终止之前更快地清理对象。

这一切都与 "scope" 和作用域链的基本概念有关。当一个项目不再在任何其他对象范围链中时,它就可以被收集。清楚地理解这一点将回答这个问题,也有助于理解闭包,闭包是项目在内存中停留的时间比您预期的要长的场景。