标准答案
- 定义:一个函数引用了外层作用域里的变量,并且这个函数在外层函数执行结束后仍然可能被调用,那么这些被引用的变量就会随着函数一起保留下来。闭包不是特殊语法,而是词法作用域和函数作为一等公民共同产生的结果。
- 用途:闭包常用于封装私有状态、函数工厂、缓存结果、保存回调上下文和实现模块化。比如计数器函数每次调用都能记住自己的 count,就是因为内部函数持有了外层变量。
- 风险:闭包本身不是内存泄漏。真正的风险是闭包被长期引用时,它引用的外层变量也不会被回收。如果闭包里持有大对象、DOM 节点、定时器或事件监听,又没有清理,就可能造成内存占用增长。
- 工程处理:需要在组件卸载、页面销毁或任务结束时解绑监听、清理定时器,并避免把不再需要的大对象放进长期闭包。
题目解析
回答闭包时,最好同时讲“是什么、能做什么、风险在哪里”。只背“函数内部返回函数”不够,因为函数嵌套不一定形成有实际意义的闭包。
闭包的内存风险来自引用关系。只要闭包还可达,被它引用的词法环境也会继续可达。
代码示例
计数器是最容易解释闭包的例子:外层函数已经执行完,但 count 仍被内部函数保存。
JavaScript
function createCounter() {
let count = 0
return function increment() {
count += 1
return count
}
}
const counter = createCounter()
counter() // 1
counter() // 2常见误区
- 把闭包等同于函数嵌套。函数嵌套只是形式,关键是内部函数引用了外层变量并可能在外层执行结束后继续使用。
- 误以为闭包一定会导致内存泄漏。只有长期持有不再需要的对象时才会形成问题。
- 只会背定义,不会说私有变量、缓存、事件回调这些使用场景。