您不必显式地“释放”JavaScript 对象。所有标准 JavaScript 主机/环境都根据对象是否可以再访问来使用垃圾收集。 (可能有一些小众主机,例如一些用于嵌入式系统的主机,它们不会这样做;如果是这样,它们将提供自己的显式释放事物的方法。)如果无法再访问该对象,则它的内存可以是回收。
你可以做的是确保没有任何东西是引用你不再使用的内存,因为被引用的内存不能被释放。几乎所有时间,这都是自动发生的。例如:
function foo() {
var a = [1, 2, 3, 4, 5, 6];
// Do something
}
分配给数组a 指向的内存有资格在foo 返回后被回收,因为它不再被任何东西引用(a 已经超出范围而没有任何突出的引用) .
相比之下:
function foo() {
var a = [1, 2, 3, 4, 5, 6];
document.getElementById("foo").addEventListener("click", function() {
alert("a.length is " + a.length);
});
}
现在,a 指向的内存无法回收,因为有一个闭包(事件处理函数)对其有活动引用,并且有一些东西将闭包保存在内存中(DOM 元素)。
您可能认为只有在上述情况下才重要,闭包清楚地使用a,但在这里不重要:
function foo() {
var a = [1, 2, 3, 4, 5, 6];
document.getElementById("foo").addEventListener("click", function() {
alert("You clicked foo!");
});
}
但是,根据规范 a 被保留,即使闭包不使用它,闭包仍然有对它的间接引用。 (更多内容请参阅我的 [相当老的] 博客文章 Closures Are Not Complicated。)有时 JavaScript 引擎可以优化 a,尽管早期的积极努力被回滚了 - 至少在 V8 中 - 因为执行此操作所需的分析对性能的影响比仅将数组保留在内存中所做的影响更大。
如果我知道闭包不会使用该数组,我可以通过为 a 分配不同的值来确保该数组不被引用:
function foo() {
var a = [1, 2, 3, 4, 5, 6];
document.getElementById("foo").addEventListener("click", function() {
alert("You clicked foo!");
});
a = undefined; // <===============
}
现在,虽然a(变量)仍然存在,但它不再引用数组,所以可以回收数组的内存。
更多内容请关注this other answer here on StackOverflow。
更新:我可能应该提到delete,尽管它不适用于您问题中的确切代码。
如果您习惯了其他一些语言,您可能会认为“啊,delete 是 new 的对应物”,但实际上两者完全彼此无关.
delete 用于从对象中删除属性。它不适用于您的代码示例,原因很简单,您无法删除vars。但这并不意味着它与您可能遇到的其他代码无关。
让我们考虑两段似乎在很大程度上做同样事情的代码:
var a = {}; // {} is the same as new Object()
a.prop = "foo"; // Now `a` has a property called `prop`, with the value "foo"
a.prop = undefined; // Now `a` has a property called `prop`, with the value `undefined`
对比
var b = {}; // Another blank object
b.prop = "foo"; // Now `b` has a property called `prop`, with the value "foo"
delete b.prop; // Now `b` has *NO* property called `prop`, at all
这两者都使prop 指向的内存符合垃圾回收条件,但有区别:在第一个示例中,我们没有删除该属性,但我们已将其值设置为undefined .在第二个示例中,我们从对象中完全删除了该属性。这不是没有区别的区别:
alert("prop" in a); // "true"
alert("prop" in b); // "false"
但这适用于您的问题,因为删除属性意味着该属性指向的任何内存都可用于回收。
那么为什么delete 不适用于您的代码?因为你的person 是:
var person;
用var 声明的变量是 对象的属性,但它们不能是deleted。 (“它们是对象的属性?”我听到你说。是的。如果你在全局范围内有一个 var,它就会成为全局对象的一个属性 [window,在浏览器中]。如果你有一个var 在函数范围内,它成为一个不可见但非常真实的对象的属性,称为“变量对象”,用于调用该函数。无论如何,你不能删除它们。更多关于the link above 中关于闭包的内容。)