您不必显式地“释放”JavaScript对象。所有标准的JavaScript主机/环境都使用基于垃圾收集的内存管理,根据对象是否可以再次访问。 (可能会有一些专门用于嵌入式系统等领域的主机不这样做; 如果是这样,它们将提供自己的手段来显式释放内容。)如果不能再次访问该对象,则可以回收其内存。
您可以确保没有任何东西正在引用您不再使用的内存,因为正在引用的内存无法释放。几乎所有时间都会自动发生。例如:
function foo() {
var a = [1, 2, 3, 4, 5, 6];
}
一旦foo
返回,指向数组a
的内存就可以被回收,因为它不再被任何东西引用(a
已经超出了范围,没有任何未解除引用的东西)。
相比之下:
function foo() {
var a = [1, 2, 3, 4, 5, 6];
document.getElementById("foo").addEventListener("click", function() {
alert("a.length is " + a.length);
});
}
现在,由于闭包(事件处理函数)具有对其的活动引用,并且有一些东西使闭包保持在内存中(DOM元素),因此a指向的内存无法被回收。
你可能认为这仅适用于上面的情况,其中闭包明显使用a,但是在这里不使用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
仍然存在,但它不再引用数组,因此可以回收数组的内存。
更多信息请参见StackOverflow上的另一个答案。
更新: 我可能应该提到delete
,尽管它不适用于你问题中的精确代码。
如果你习惯了其他语言,你可能会认为"啊,delete
是new
的对应物",但实际上两者完全没有任何关系。
delete
用于从对象中删除属性。它不适用于你的代码示例,因为你不能删除var
。但这并不意味着它与你可能遇到的其他代码无关。
让我们考虑两个看起来基本相同的代码片段:
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
声明的变量是对象的属性,但它们不能被删除。("它们是对象的属性?"你会问。是的。如果你在全局作用域有一个
var
,它就成为全局对象[在浏览器中是
window
]的属性。如果你在函数作用域中有一个
var
,它就成为一个不可见但非常真实的对象的属性,该对象称为“变量对象”,用于对该函数的调用。无论哪种方式,你都不能删除它们。有关此问题的更多信息,请参见
上面的链接关于闭包的内容。)
new Object()
=>{}
; 2. 它依赖于自动分号插入,如果不是恶魔的产物,仍然是一件你绝对不能依赖的事情;3. 好吧,这一点还不错,但是,为什么不教直接量表示法呢?var person = {name: "Tim Scarfe", height: "6Ft"};
但实际上,它是#2,稍微有点#1,让我想到了“blech”。 - T.J. Crowder