前端面试题

JavaScript闭包与作用域链

什么是闭包?讲讲经典的循环setTimeout坑。

为什么面试官会问这道题

闭包是JS"会用"和"懂原理"的分水岭,几乎每场JS面试都要考。

如何回答

  1. 1

    闭包:函数+它定义时的词法环境。"关闭"了那个环境里的变量。

  2. 2

    作用域链:查找变量时JS从最内层往外沿着词法环境链一路找。

  3. 3

    经典题:`for (var i=0; i<3; i++) setTimeout(()=>console.log(i))`输出3,3,3——var是函数作用域,三个回调共享同一个i。

  4. 4

    修:改成let(块作用域,每轮新binding)或用IIFE捕获当前值。

  5. 5

    内存:闭包持引用;闭包活得比作用域久,被捕获的变量就回收不掉。常见泄漏源。

参考回答示例

闭包=函数+它出生那个作用域,即便外层函数返回了也还能访问那些变量。经典题:var循环+setTimeout回调。var是函数作用域,三个回调引用同一个i,执行时i已经是3,所以3,3,3。换成let每轮都是新binding,就是0,1,2。我故意用这个模式做数据私有——只暴露操作私有状态的方法,不用挂在对象上。内存注脚:DOM节点被闭包引用又活得比节点久就是经典泄漏,addEventListener最常见。

实用技巧

  • ES6模块免费给你私有性——纯为隐私用闭包现在用得少,但库里还常见。

  • DevTools→Memory→Heap snapshot里闭包是单独分类——排泄漏利器。

  • 即答侠整理了闭包TOP5坑,一看形状就能认出来。

常见问题

是不是所有函数都是闭包?

严格说是——每个函数都捕获词法环境。实际只有外层作用域已经消失时我们才叫"闭包"。

箭头函数和普通函数闭包区别?

作用域语义一样。差别在`this`绑定(箭头继承,普通自带)和arguments/new.target。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠