闭包是函数和在其中声明该函数的词法环境的组合。
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)) }