关闭 - 当创建一个新的闭包时,现有闭包会发生什么?

时间:2011-05-02 15:18:10

标签: javascript memory closures

document.getElementById("innbutt").onclick = (function(){
    var newvar = "hello"; 
    return function(){
        alert(newvar);
    }
})();

当我们一直点击innbutt时,新的闭包会不断创建。

那么,旧的会发生什么?
1)它被删除了吗? OR
2)它是否留在记忆中?

修改:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}
window.onload = addLinks;

来源:javascript scope and closures
在这种情况下,link.onclick处理程序只创建了一个闭包?

2 个答案:

答案 0 :(得分:4)

只创建一个闭包

因为你误解了事件处理程序的概念。

document.getElementById("innbutt").onclick = (function(){
    var newvar = "hello"; 
    return function(){
        alert(newvar);
    }
})();

可以说相当于:

document.getElementById("innbutt").onclick = function() {
    alert("hello");
};

因为在第一种情况下,立即执行的函数返回匿名alert并且被分配给onclick处理程序。每当您单击按钮时,都会执行此特定的匿名函数。在您错误地思考时,不会处理新的onclick处理程序分配。

答案 1 :(得分:2)

首先要注意的是,每次单击innbutt时都不会重新创建包含newvar定义的原始闭包。它执行了一次,并且该闭包内的命名空间一直存在,直到您删除对执行警报的内部函数的所有引用。所以要回答你的第一个问题,关闭不会被删除。要回答第二个问题,闭包内的命名空间将一直保留,直到您删除对分配给innbutt onclick的函数的所有引用。换句话说,如果将onclick设置为null,则闭包将不再保留在内存中,除非在此之前将该函数分配给另一个变量。

这是一个类似于你的例子的例子。这个例子有一个闭包,它立即执行,然后返回一个有权访问该持久性闭包的命名空间的函数:

secrets = (function() {
  var mySecrets = {};
  return function(name, value) {
    if(arguments.length < 2)
      return mySecrets[name + ""];
    mySecrets[name + ""] = value;
  };
})();

// Set my name.
secrets("my name", "Chris West");

// Set my friend's name.
secrets("my friend's name", "John Jacob");

// Get my name and my friend's name.
alert("My name is " + secrets("my name") + ".\n"
  + "My friend's name is " + secrets("my friend's name") + ".");

// Alias the secrets function.
fnSecrets = secrets;

// Remove one reference to the secrets function.
secrets = null;

// Remove the second reference to eliminate the closure from memory.
fnSecrets = null;

请注意,secrets函数实际上是在闭包内返回的函数。此外,此函数可以访问mySecrets,它是闭包内的变量。自从我写了fnSecrets到别名的秘密后,一旦我搞清楚了秘密,关闭仍然存在,直到fnSecrets被淘汰。