作用域、函数与生命周期
函数需要同时追踪三种关系:名字通过词法环境找到哪个绑定,this 通过调用形式或词法外层取得哪个接收者,以及谁还持有这个函数使相关对象继续存活。闭包、回调和泄漏不是三个独立口诀,而是一张可以沿引用和时间顺序解释的关系图。
核心模型
函数需要同时追踪三种关系:名字通过词法环境找到哪个绑定,this 通过调用形式或词法外层取得哪个接收者,以及谁还持有这个函数使相关对象继续存活。闭包、回调和泄漏不是三个独立口诀,而是一张可以沿引用和时间顺序解释的关系图。
原理与机制
闭包保留可访问的绑定,不自动拍快照
函数创建时关联词法环境,之后调用会读取绑定当前值。for(var i...) 中多个回调共享函数作用域的 i,结束后都可能看到最终值;for(let i...) 为迭代建立相应绑定,各回调可保留各轮值。必须用 var 时,每轮调用工厂或 IIFE,通过独立参数绑定保存编号。如果参数是同一个对象,各次复制的是引用,仍会看到后续对象修改;需要快照时必须明确复制范围,而不是把创建闭包当成克隆。
作用域存在与绑定初始化是两回事
let、const、class 的绑定在作用域进入后就影响名字解析,但初始化前处于暂时性死区。typeof 未声明名字返回字符串 undefined,是专门规则;typeof 内层未初始化 let 仍抛 ReferenceError,外层同名值也被遮蔽。var 常先初始化为 undefined,提升不意味着引擎物理移动代码。默认参数从左向右初始化,f(a=b,b=1) 在 a 使用默认值时会读取尚未初始化的 b;传 null 不触发默认值,传 undefined 会。switch 的 case 默认共享块,可用独立块限定声明。
this 取决于调用契约
普通函数通过 obj.method() 调用时接收者是 obj;取出成 f() 后严格模式下 this 通常为 undefined。call/apply 显式给接收者,bind 创建固定接收者的新函数。箭头函数没有自身 this,只沿词法外层读取,不能再被 call/bind 改写,也不能 new。对象字面量不是独立 this 作用域,所以里面的箭头函数不会自动绑定对象。绑定原方法与包装 ()=>obj.method() 还不同:前者保留原函数,后者每次重新查当前方法。
函数身份连接订阅与清理
每次 bind 都产生新函数,注册和移除分别 bind 会不匹配。可构造时绑定一次保存,或用实例箭头字段;原型方法可共享,但两种绑定方式通常都增加每实例函数。removeEventListener 关键匹配事件类型、同一函数引用与 capture,不要求 passive/once 完全复写;capture 两种注册要分别移除。支持 signal 的监听可用同一 AbortController 集中终止,但必须实际 abort,不能只创建控制器。
内存回收看可达性,资源释放看责任
长期事件源、定时器或全局 Map 若持有回调,回调就可能继续保留编辑器实例及大数组。不可达循环可以回收,无环但一直可达的缓存也会无限增长。用可重复打开关闭场景,比较堆快照、保留路径与 detached DOM,排除正常缓存、延迟回收和工具自身引用。生命周期结束时幂等 dispose,退订、清计时器、关闭连接或 worker;WeakMap 不延长键寿命,但不能替代及时清理,FinalizationRegistry 的调用时机甚至是否发生都不可靠。
最小示例
javascript预期输出 [0,1,2]、1 2、false。把循环 let 改为 var 后输出会变成 [3,3,3];bound 保留旧方法和接收者,wrapped 查到新方法;最后两次 bind 身份不同,即使目标相同也不能互相作为监听清理引用。此片段无 DOM,事件清理仍需浏览器例程验证。
环境:现代 Node.js;可保存为 .cjs 后执行。
核验:未执行教学示例;说明中的结果为机制推演,不是本轮测试通过记录。
边界与取舍
边界
- const 禁止重新绑定,不会深冻结对象;把局部变量设 null 也不清除其他持有者。
- 闭包不是泄漏证据,循环引用也不是;需要证明不再使用的数据仍由长寿命根保留。
- 箭头函数解决词法 this,不自动处理监听退出、实例数量或资源生命周期。
取舍
- 实例箭头字段传回调方便,但每实例有独立函数;原型方法更便于共享与继承,需明确绑定策略。
- 缓存和闭包可减少重复计算,也会延长数据存活;容量、失效和 dispose 应成为接口契约。
口述示范
我解释闭包时先画绑定与调用时间,解释 this 时看实际调用式,解释泄漏时沿根对象找保留路径。回调需要稳定身份和对称清理,不能靠再 bind 一次、设 null 或等待垃圾回收释放必须及时关闭的资源。
章节练习
参考来源与核验边界
- ECMAScript:Functions and classes · 核验 2026-10-04
- ECMAScript:Execution contexts · 核验 2026-10-04
- WHATWG:DOM EventTarget · 核验 2026-10-04
核验日期 2026-10-04。严格模式是 this 示例前提;垃圾回收与 finalizer 不承诺即时执行。DOM 监听的 signal 选项需依目标环境确认。 本章新增示例未在本轮执行,不新增测试通过声明。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。