闭包通过捕获外层函数中被引用的自由变量(如_this、args、timer等),使其在堆内存中长期存活,从而维持关键上下文;它不保存完整执行上下文或this/arguments,需开发者显式缓存;每次调用工厂函数生成独立闭包实例,变量彼此隔离。

闭包本身不“保持”完整的执行上下文,而是通过捕获并持有外层函数作用域中被引用的自由变量,让这些变量在堆内存中长期存活,从而在后续调用中恢复关键上下文信息(如 this、参数、时间戳、定时器 ID 等)。
闭包保存的是变量引用,不是整个执行上下文
函数执行完毕后,其执行上下文会从调用栈弹出,变量对象本该被回收。但若内部函数引用了外层的某个变量(比如 timer、lastExec、_this),JS 引擎就会保留该变量所在的词法环境记录(存在于堆中),供闭包持续读写。
- 不是把
this、arguments直接打包存起来——它们不会被闭包自动捕获 - 而是开发者显式地把需要的值赋给外层变量(如
const _this = this、const args = arguments),再由内层函数引用这些变量 - 真正被保留的,是这些变量在堆中的绑定,而非栈帧或完整上下文结构
关键上下文信息靠手动缓存 + 闭包维持
事件回调中常见的 this 和参数丢失问题,必须靠开发者主动缓存,闭包只是让缓存值不被回收:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
this:在返回的闭包函数外层,用
const _this = this保存当前调用对象 -
参数:用
const args = arguments或展开语法[...arguments]保存实参列表 -
状态标识:如防抖的
timer、节流的时间戳lastExec,都声明在外层,被闭包函数反复读写 - 最终在定时器或条件满足时,通过
func.apply(_this, args)恢复原始调用环境
每个闭包实例拥有独立的作用域链
每次调用 debounce() 或 throttle() 都会生成一个新的外层函数执行,也就创建一组新的闭包变量(timer、_this、lastExec 等)。不同绑定目标互不影响:
- 一个输入框的防抖函数和另一个按钮的节流函数,各自维护自己的
timer和lastExec - 这种隔离性正依赖于闭包——每个返回的函数都绑定自己专属的词法环境
- 引擎为每次工厂函数调用分配独立的堆内存块,彼此不共享
闭包不保存执行栈,只维系堆中变量可达性
执行上下文栈(ECStack)只负责调度,不存储数据;而闭包通过函数的 [[Environment]] 内部属性,静态指向创建时的词法环境(位于堆中):
- 外层函数早已退出,栈里没有它的痕迹,但堆里的
_this和args仍可被访问 - 只要闭包函数还被引用(比如挂载在 DOM 事件上、赋值给变量、存入数组),它所依赖的堆环境就不会被 GC 回收
- 一旦解除所有引用(如移除监听器、设为
null),相关变量才可能释放
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










