You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS事件监听代码中点击按钮count为何逐次递增?闭包如何生效?

闭包形成逻辑与示例代码运行原理解答

你给出的示例代码如下:

function attachEventListeners() {
    let count = 0
    document.getElementById("clickMe").addEventListener("click", function () {
        console.log("Button Clicked", ++count)
    })
}
attachEventListeners()

你对闭包的认知存在一个小偏差:闭包生效的核心条件是内部函数被外部作用域持有引用、且内部函数访问了外层函数的变量,并不是必须要通过return将内部函数返回并赋值给变量才可以。

这段代码的运行和闭包形成过程如下:

  • 调用attachEventListeners时,函数作用域内会创建初始值为0的局部变量count
  • 执行addEventListener方法时,作为参数传入的匿名点击回调函数,会被浏览器的事件管理系统持有引用,不会随着attachEventListeners执行结束而被销毁
  • 这个匿名回调函数访问了外层作用域的count变量,因此形成闭包:attachEventListeners执行完成后,原本应该被回收的函数作用域因为回调函数的引用被保留,count变量也随之留存,不会被重新初始化
  • 后续每次触发按钮点击事件时,执行的都是同一个回调函数,访问的都是同一个被留存的count变量,因此可以实现逐次递增的效果

你之前认知里的「返回内部函数赋值给变量」只是闭包的常见使用场景之一,和当前示例的本质逻辑完全一致:都是内部函数逃出了外层函数的作用域范围,被外部其他模块持有引用,从而让外层函数的局部变量可以跨越作用域生命周期被持续访问。
如果多次调用attachEventListeners,每次调用都会生成独立的count变量和独立的事件回调,点击按钮时会按照绑定顺序触发多个回调,每个回调只累加自己绑定的count值。

内容的提问来源于stack exchange,提问作者anandsr-dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:12:03