闭包面试题
闭包(Closure) 是指一个函数能够记住并访问其词法作用域(定义时的作用域),即使该函数在其词法作用域之外执行。
一、通俗理解(面试可这样开头):
> 闭包就是一个函数“记住”了它出生时的环境,即使它跑到了别的地方执行,还是能访问到原来环境中的变量。
二、核心要点(面试回答建议按这个逻辑):
1. 函数嵌套:闭包通常发生在函数内部定义了另一个函数,并且内部函数引用了外部函数的变量。
2. 变量持久化:即使外部函数已经执行完毕,内部函数仍然可以访问外部函数的局部变量,这些变量不会被销毁。
3. 作用域链:闭包的本质是 JavaScript 的词法作用域(静态作用域)和作用域链的体现。
4. 常见用途:
- 封装私有变量
- 实现数据隔离
- 在定时器、事件监听、回调函数中保持状态
- 模块化开发(如早期 IIFE 模块模式)
三、代码示例(面试可简单手写):
function outer() { let count = 0; // 外部函数的局部变量 return function inner() { // 内部函数(闭包) count++; console.log(count); }; } const counter = outer(); // outer 执行完,count 本应销毁,但因为闭包,它被 inner 记住了 counter(); // 1 counter(); // 2
> 上面的 inner
函数就是一个闭包,它可以访问 outer
函数中的 count
变量,即使 outer
已经执行完毕。
四、面试回答模板(推荐):
> “闭包是指一个函数可以访问并记住其词法作用域,即使该函数在其定义的作用域之外执行。简单来说,就是内部函数引用了外部函数的变量,导致外部函数的变量不会被垃圾回收,从而形成‘闭合’的环境。闭包常用于封装私有变量、实现数据私有化、在异步回调中保持状态等场景。例如,一个函数返回一个内部函数,这个内部函数可以访问外部函数的局部变量,即使外部函数已经执行结束。”
五、注意事项(可补充):
- 闭包可能导致内存泄漏(比如不再使用的闭包没有释放引用),因此要合理使用。
- 在循环中创建闭包要注意变量捕获问题(经典面试题:for 循环中 setTimeout 打印 i 的问题)。
✅ 总结一句话(适合面试最后总结):
闭包就是函数“记住”并可以访问它定义时的作用域,是 JavaScript 作用域和函数特性的重要体现,也是实现很多高级功能的基础。