闭包会导致内存泄漏吗?如何避免?

闭包本身不是内存泄漏,它只是让变量的生命周期延长到与闭包一致。但如果闭包长期存在且不再需要引用的变量,就会造成实际的内存泄漏。

什么情况下闭包会导致内存泄漏

// 1. 意外引用:闭包引用了大对象但不使用
function createHandler() {
  const hugeData = new Array(1000000).fill('*')
  return function () {
    console.log('handler')  // 没用到 hugeData,但它被闭包引用了
  }
}
const handler = createHandler()  // hugeData 无法被回收

// 2. 定时器未清除
function startTimer() {
  const data = getData()
  setInterval(() => {
    console.log(data)  // data 一直被引用
  }, 1000)
}

// 3. DOM 事件监听未移除
function bindEvent() {
  const element = document.getElementById('btn')
  const heavyData = { /* ... */ }
  element.addEventListener('click', () => {
    console.log(heavyData)
  })
  // 如果 element 被移除但监听器未移除 → 泄漏
}

如何避免

  1. 及时清除引用:用完后将变量设为 null
  2. 清除定时器:clearInterval() / clearTimeout()
  3. 移除事件监听:removeEventListener()
  4. 使用 WeakMap / WeakSet:不阻止 GC 回收
// WeakMap 解决方案
const cache = new WeakMap()
function process(obj) {
  if (!cache.has(obj)) {
    cache.set(obj, expensiveCompute(obj))
  }
  return cache.get(obj)
}
// 当 obj 被回收,cache 中的条目也会被自动清除

现代浏览器

现代 V8 引擎已经能优化未使用的闭包变量,但在以下场景仍需注意:

同分类其他题目