JavaScript无返回IIFE内绑定事件监听器的私有函数可执行原因咨询
核心问题:你对闭包的触发条件存在误解
闭包的产生完全不依赖外层函数有没有返回值,只要内部函数被拿到了它定义时的词法作用域之外被引用/执行,就会形成闭包,对应的外层作用域也会被保留不会被垃圾回收。
你代码中的闭包形成逻辑:
controller这个IIFE执行时,会创建属于它的函数作用域,作用域内包含了setupEventListener、privateFunction、updateGame三个函数。- 你调用
setupEventListener时,把内部定义的updateGame作为回调传给了document.addEventListener,这一步本质就是把updateGame这个内部函数,挂载到了全局的document对象上,等于它已经被拿出了controllerIIFE的原始作用域,此时闭包已经形成。 - JavaScript的词法作用域规则是:函数的作用域在定义阶段就已经确定,和执行位置无关。
updateGame定义在controllerIIFE的作用域中,它内部的[[Scopes]]属性会永久持有这个作用域的引用。 - 虽然
controllerIIFE执行完会被弹出调用栈,但因为document的事件监听器还持有updateGame的引用,而updateGame又持有controllerIIFE作用域的引用,所以这个作用域不会被垃圾回收,里面的privateFunction自然也会保留。
补充说明
你之前接触的「IIFE返回对象生成闭包」只是闭包最常见的使用场景,不是唯一触发条件:把内部函数赋值给全局变量、作为回调传给事件监听器、定时器、异步请求API等场景,都会把内部函数拿到外层作用域,都会形成闭包。
内容的提问来源于stack exchange,提问作者Kevo
相关产品推荐
相关产品推荐

