内存堆栈如何在javascript中工作

时间:2010-04-20 18:33:40

标签: javascript memory stack

我们的代码如下:

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()完成,那么()中'x'的值是否应该'消失'?包含x的堆栈也应该也消失了吧?或者,javascript是否始终保留所有堆栈,以防将来引用它们?但这不会很好,是吗......?

2 个答案:

答案 0 :(得分:6)

你要找的词是“封闭”。

在另一个函数内创建function,为内部函数提供对外部函数运行的本地作用域的(隐藏)引用。

只要您保留test的副本,其中明确引用add函数,函数具有对创建范围的隐式引用调用a构造函数时。 范围具有对x的明确引用,以及函数中定义的任何其他局部变量。 (包括this值和构造函数arguments - 虽然您无法从add内部访问它们,因为该函数自己的this / arguments正在影响它们。)

当你放开test时,JavaScript解释器可以放弃x,因为无法获得对该变量的引用。

答案 1 :(得分:4)

您所看到的是closure的效果。在另一个函数中定义的函数可以访问所有变量,也可以在范围内访问 - 即使在外部函数返回之后。 More here,但基本上,函数中的变量(和参数)都作为与该函数调用相关的对象(称为“变量对象”)的属性存在。因为您绑定到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,以便释放内容。)