为什么变量counter在第一次点击时被设置为0。
这不是设置为 0 的时刻。这发生在分配给 .onclick 的时候。在那一刻,outer 被定义并执行。这就是 counter 设置为 0 的时刻。尚未处理任何点击。
只有函数 inner() 被执行
确实如此。 outer 仅在页面加载时执行主脚本时执行一次,然后再也不执行。 inner 是分配给onclick 的函数,因此具有事件处理程序的角色。 inner 可以访问在outer 中定义的counter,但outer 永远不会再次执行。
outer是所谓的立即执行函数。
作为比较:您可以使用此代码实现类似的效果:
var counter = 0;
element.onclick = function inner() {
counter++;
alert('Number of clicks: ' + counter);
};
...但现在的缺点是counter 是一个全局变量,可以通过其他代码进行更改。为了确保counter 仅可用于点击处理程序,为它创建了一个闭包,您也可以这样做:
function outer() {
var counter = 0;
element.onclick = function inner() {
counter++;
alert('Number of clicks: ' + counter);
};
}
outer();
这里的缺点是outer 有一个所谓的副作用:它分配给element.onclick。这就是选择 return inner 并将其留给 outer 的调用者来处理它的原因,例如将其分配给.onclick。
然后我们得到这样的东西:
function outer() {
var counter = 0;
return function inner() {
counter++;
alert('Number of clicks: ' + counter);
};
}
element.onclick = outer();
这与您的代码基本相同:首先定义函数,然后立即执行。分配给onclick 的函数是outer 返回的函数,即inner。
实现counter这种封装的另一种方式:
function inner() {
this.counter++;
alert('Number of clicks: ' + this.counter);
}
element.onclick = inner.bind({ counter: 0 });
这里我们提供了一个未命名的对象,无论何时调用它,它总是作为this-argument 传递给inner。由于我们没有在这个构造之外保留对该对象的引用,因此我们实现了相同的原则:保持计数器的状态,但在处理程序之外无法访问。