什么是闭包
What is a closure
一句话:函数记住了它定义时所在的作用域—— 即使外层函数已经执行完了, 里面的变量也还活着,因为这个函数还在引用它们。
为什么会这样?因为作用域链在定义时就绑好了(#297)。 外层函数返回后, 它的变量本该被回收, 但只要还有函数引用着, 垃圾回收就不会动它。
四个真实用途(面试要的是用途,不是定义):
- 私有状态—— 计数器、缓存。 外部拿不到那个变量,只能通过你暴露的方法改。
- 防抖 / 节流—— 用闭包存 timer。
- 柯里化 / 偏函数—— 记住已经传进来的参数(#299)。
- React 的 Hooks 全靠它——
useState返回的setState、useEffect里的回调, 都是闭包捕获了那一次渲染的值。「过期闭包」这个 bug 就是它的副作用。
会追问的两道题:
① 循环里的 setTimeout(见 #282)。var 全程只有一个 i, 三个闭包共享它;let每次迭代新建一个绑定,所以各自记住自己那份。
② 闭包会不会造成内存泄漏?会 —— 如果闭包一直存活(比如挂在全局或未移除的事件监听里), 它引用的整个作用域都回收不了。解法是及时解绑, 这也是 React 里 useEffect必须写清理函数的原因之一。
In one line: a function remembers the scope it was defined in — even after the outer function has finished, the variables inside are still alive, because that function is still referencing them.
Why does that happen? Because the scope chain is wired up at definition time (#297). Once the outer function returns, its variables would normally be collected, but garbage collection leaves them alone as long as some function still references them.
Four real uses — the interview wants uses, not the definition:
- Private state — counters, caches. Nothing outside can reach the variable; it can only go through the methods you expose.
- Debounce and throttle — the closure holds the timer.
- Currying and partial application — remembering the arguments received so far (#299).
- Every React Hook rests on it — the
setStatereturned byuseState, and the callback insideuseEffect, are closures that captured the values of one particular render. The “stale closure” bug is the flip side of that.
Two follow-ups to expect:
① setTimeout inside a loop (see #282). With var there is one i for the whole loop and all three closures share it; let creates a new binding per iteration, so each closure remembers its own.
② Can a closure leak memory? It can — if the closure stays alive (hanging off a global, or an event listener you never removed), the entire scope it references cannot be collected. The fix is to unsubscribe in time, which is one of the reasons a React useEffect needs its cleanup function.