当我们有如下代码时:
function a(){
var x =0;
this.add=function(){
alert(x++);
}
}
var test = new a();
test.add(); // alert 0
test.add(); // alert 1
test.add(); // alert 2
这是如何运作的?
一旦test = new a()完成,难道不是a()中的'x'值应该为'gone'吗?包含x的堆栈也应该消失,对吗?或者,javascript是否会始终保留所有已创建的堆栈,以防将来被引用?但这不是很好,是吗...?
最佳答案
您所看到的是closure的效果。在另一个函数中定义的函数即使在外部函数返回后也可以访问所有变量,并且可以访问其所在的范围。 More here,但基本上,函数中的变量(和参数)都作为与该函数调用相关的对象(称为“变量对象”)的属性存在。由于您绑定(bind)到this.add
的函数是在该上下文中定义的,因此它对该对象具有持久的引用,从而可以防止该对象被垃圾回收,这意味着该函数可以继续访问那些属性(例如,变量和函数的参数)。
通常,您会听到人们说函数关闭了x
变量,但是它比这更复杂(更有趣)。持久访问变量对象。这具有影响。例如:
function foo() {
var bigarray;
var x;
bigarray = /* create a massive array consuming memory */;
document.getElementById('foo').addEventListener('click', function() {
++x;
alert(x);
});
}
乍一看,我们发现点击处理程序只使用过
x
。因此,它仅引用了x
,对吗?错误的是对变量对象的引用,该对象包含
x
和bigarray
。因此,即使该函数不使用bigarray
的内容,它的内容也将保留下来。这不是问题(它经常有用),但是它强调了底层机制。 (并且,如果您确实不需要单击处理程序中的bigarray
的内容,则可能要先从bigarray = undefined;
返回之前执行foo
,以便释放内容。)