闭包是能访问并“记住”其定义时词法作用域变量的函数,本质是作用域链的延续;易致内存泄漏因长期持有大对象或DOM引用而阻碍垃圾回收,需通过解绑事件、清理定时器、置空引用等方式避免。
闭包是 JavaScript 中一个函数,它不仅包含自身函数体,还“记住”并能访问其定义时所处的词法作用域中的变量。换句话说,只要一个函数引用了外层函数的局部变量,哪怕外层函数已经执行完毕,这个内层函数仍是闭包。
JS 执行时会为每个函数创建执行上下文,其中包含词法环境(Lexical Environment)。闭包之所以能访问外部变量,是因为它的内部 [[Environment]] 引用链一直指向外层作用域。即使外层函数返回、执行栈清空,只要闭包还存在且被引用,那块词法环境就无法被垃圾回收器标记为“不可达”。
内存泄漏不是闭包本身的问题,而是**闭包意外长期持有本该释放的大对象或 DOM 引用**,导致 GC 无法回收。关键在于:闭包延长了外部变量的生命周期,而开发者没及时切断引用链。
不是所有闭包都危险。如果闭包只捕获几个小字符串或数字,或者闭包本身很快被置为 null,GC 会在下一轮标记清除中顺利回收。真正危险的是:闭包持有了大数组、大对象、完整
DOM 树,又长期被全局变量、事件、定时器等强引用维系着。
核心思路是:让闭包引用的对象在不需要时变成“不可达”。常用手段包括: