Java闭包的实际用途?

闭包是函数和在其中声明该函数的词法环境的组合。

function outerFunc() {
   var name = "nhooo"; // name is a local variable created by outerFunc
   return function innerFunc() {
      // innerFunc() is the inner function, a closure
      console.log(name); // use variable declared in the parent function
   };
}
let f = outerFunc();
f()

outsideFunc()创建一个名为name的局部变量和一个名为的函数innerFunc()。该innerFunc()函数是在内部定义的内部函数,outerFunc()仅在outerFunc()函数主体内可用。

请注意,该innerFunc()函数没有自己的局部变量。但是,由于内部函数可以访问外部函数innerFunc()的变量,因此可以访问在父函数中声明的变量名outerFunc()

您可以看到,outerFunc完成执行后,该名称已超出范围。但是,如果仔细观察,返回并分配给f的innerFunc仍然可以访问name变量。因此,内部函数在outerFunc的词法范围内形成了一个闭合。

实际用途

模拟私有方法-Java之类的语言提供了将方法声明为私有的能力,这意味着它们只能由同一类中的其他方法调用。JavaScript没有提供执行此操作的本机方法,但是可以使用闭包来模拟私有方法。

示例

var counter = (() => {
   var privateCounter = 0;
   let changeBy = (val) => privateCounter += val;
   return {
      increment: () => changeBy(1),
      decrement: () => changeBy(-1),
      value: () => privateCounter
   };
})();
console.log(counter.value());
counter.increment();
counter.increment();
console.log(counter.value());
counter.decrement();
console.log(counter.value());

输出结果

0
2
1

与事件处理程序一起使用

for(let i = 0; i < 4; i++) {
   button = buttons[i]
   button.addEventListener("click", alert(i))
}

如果在集合按钮中有4个按钮,并尝试添加这样的事件侦听器,则对这些按钮的任何单击最终都将给出未定义的结果。这是因为当它们被调用时,我将不再被定义。解决此问题的方法是在i上引入闭包。

for(let i = 0; i < 4; i++) {
   button = buttons[i]
   button.addEventListener("click", () => alert(i))
}