<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<script>
const buttons = document.querySelectorAll('button');
buttons.forEach((button, index) => {
let clickCount = 0;
button.addEventListener('click', (function (btnIndex) {
return function () {
clickCount++;
console.log(`按钮 ${btnIndex + 1} 被点击了 ${clickCount} 次`);
};
})(index));
});
</script>
</body>
</html>
闭包与事件处理器协作解释
- 闭包创建:在
forEach
循环中,通过立即执行函数表达式(IIFE)(function (btnIndex) { ... })(index)
创建了闭包。每次迭代,这个IIFE都会创建一个新的作用域,btnIndex
作为这个作用域的局部变量被捕获。同时,clickCount
变量也在这个作用域内声明,每次循环都有独立的 clickCount
实例。
- 事件处理器关联:IIFE返回一个函数,这个函数作为事件处理器被添加到对应的按钮上。当按钮被点击时,执行这个返回的函数。由于闭包的特性,这个返回的函数可以访问并操作它外部函数(IIFE)作用域中的
clickCount
和 btnIndex
变量。尽管外部函数(IIFE)已经执行完毕,但是它的作用域因为被返回的函数引用而得以保留,使得每次点击按钮时,clickCount
能够正确累加并显示每个按钮独立的点击次数。