这两个闭包有什么区别?

What is the difference in these two closures?

我最近了解到有几种方法可以创建闭包(不仅仅是从函数返回函数),还可以在事件侦听器中将函数引用为回调。这也创建了一个闭包,它解释了为什么即使在 IIFE 已完成执行并且没有返回任何内容之后,您也可以使用 eventListener 调用 innerFunction。

我认为闭包的主要功能在于它不仅可以在外部函数中找到一个变量供内部函数使用,而且还可以更新它的值以便存储。例如,您可以推入一个数组并在外部函数内更新它,或者将分数集更新为外部函数的原语。

但是,如果您可以通过事件侦听器引用函数来创建闭包,那么为什么您不能在每次通过事件侦听器调用函数时更新局部变量,请参阅下文了解我想要获得的内容在

function increaseScore(){
   var score = 0;
   score ++;
   console.log(score); // console.logs one everytime the event occurs
                       // despite the event listener creating a
                       // closure for this funciton
}
document.addEventListener("click", increaseScore);

function addScore(){
  var score = 0;

  return function (){ // This too is a closure created in a different way
                      // and increases every time the event is called
   score ++;
   console.log(score); // 1, 2, 3, 4, etc. every time the event occurs
  }
}
var keepScore = addScore();
document.addEventListener("click", keepScore);

为什么会这样?它们都是闭包的例子,一个是通过事件监听器,另一个是通过返回一个函数,但只有 returns 函数从其原始值零更新并在每次函数执行时保存在内存中的函数调用并且第一个函数每次都重置为零,因此只会将 1 打印到控制台。我到处都找不到解释。

第一个不是闭包,因为 var score 是在 函数中声明的。一旦将该行移到函数之外,它将按预期工作(并且函数将关闭全局变量):

var score = 0;
function increaseScore(){
  score ++;
  console.log(score);
}
document.addEventListener("click", increaseScore);

如何在不 return 的情况下创建闭包的更好示例可能是

var keepScore;
function addScore(){
  var score = 0;

  keepScore = function (){ // this too is a closure
    score++;
    console.log(score);
  };
}
addScore();
document.addEventListener("click", keepScore);
function addScore(){
  var score = 0;

  function keepScore(){ // this too is a closure
    score++;
    console.log(score);
  };
  document.addEventListener("click", keepScore);
}
addScore();