首页 > 解决方案 > 这两个闭包有什么区别?

问题描述

我最近了解到有几种方法可以创建一个闭包(不仅仅是从函数中返回一个函数),而且还可以在事件侦听器中将函数引用为回调。这也创建了一个闭包,它解释了为什么即使在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);

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

标签: javascriptclosuresiife

解决方案


第一个不是闭包,因为函数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();

推荐阅读