【前端每天一题】第 23 题:闭包(Closure)与作用域链(详细 + 面试模板 + 速记卡)

好的,继续 第 25 题:闭包(Closure)与作用域链(详细 + 面试模板 + 速记卡)


第 25 题:闭包(Closure)与作用域链

闭包是前端面试必考题,几乎每家公司都会问。

我会用非常详细但清晰的方式讲解。


一、闭包是什么?

闭包 = 函数 + 其定义时的词法环境(外部变量)

简单说:
闭包让函数可以"记住"它定义时的外部变量,即使外部函数已经执行完毕。

比如:

scss 复制代码
function outer() {
  let count = 0;
  return function inner() {
    count++;
    console.log(count);
  };
}

const fn = outer();
fn(); // 1
fn(); // 2

即使 outer() 执行完,count 仍然能被访问,这就是闭包。


二、闭包形成的原因:词法作用域

JS 采用 词法作用域(静态作用域) ,作用域在函数定义时已经确定。

所以 inner 函数能访问 outer 的变量。

编译阶段就决定了作用域链,运行时不会改变。


三、闭包的用途(面试重点)

1. 创建私有变量

javascript 复制代码
function createCounter() {
  let num = 0;
  return {
    inc() { num++; },
    get() { return num; }
  }
}

2. 防抖 / 节流、缓存函数里面常用

vbnet 复制代码
function cache(fn) {
  const map = {};
  return function(key) {
    if (map[key]) return map[key];
    return map[key] = fn(key);
  };
}

3. 柯里化 Currying

css 复制代码
const add = a => b => a + b;

4. 模拟块级作用域(ES5 时代)

javascript 复制代码
for (var i = 0; i < 3; i++) {
  setTimeout((function(i){ 
    return function() { console.log(i) }
  })(i), 1000);
}

四、闭包的缺点(面试必问)

❗闭包会导致变量常驻内存,可能造成内存泄漏

例如:

javascript 复制代码
function test() {
  let data = new Array(100000).fill(0);
  return function() {
    console.log(data.length);
  }
}
const f = test();

data 一直无法释放,因为闭包引用它。


五、作用域链(Scope Chain)

作用域链 = 当前作用域 → 外部作用域 → 全局作用域

查变量是从内到外一层层查。

示例:

ini 复制代码
var a = 1;

function f1() {
  var b = 2;
  function f2() {
    var c = 3;
    console.log(a, b, c);
  }
  f2();
}
f1();

作用域链查找顺序:

csharp 复制代码
f2 → f1 → global

六、面试官常问三连

① 闭包是什么?

闭包是在函数创建时,把函数和它的词法作用域绑定在一起,使函数在外部作用域结束之后仍然能访问该作用域的变量。

② 闭包有什么用?

私有变量、缓存、柯里化、防抖节流内部状态、回调函数等。

③ 闭包有什么风险?

变量不会释放,容易造成内存泄漏,如不需要应置为 null 或使用块级作用域优化。


七、经典闭包题 --- 面试必考

❗例题:

css 复制代码
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

输出?

复制代码
3 3 3

原因:

  • var 没有块级作用域
  • 三个回调共享同一个 i
  • 当执行回调时,i 已变为 3

改成 let:

css 复制代码
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

输出:

复制代码
0 1 2

八、速记卡片

复制代码
闭包 = 函数 + 外部变量
作用:记住状态(私有变量、缓存)
关键:词法作用域决定作用域链
风险:内存泄漏(变量无法释放)

如果你准备好了,我可以继续 第 26 题:前端性能优化(重排/重绘、懒加载、打包优化) 。

说一句:"下一题"即可。

相关推荐
孟陬1 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端
Zhao-Jichao1 小时前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端
Highcharts.js2 小时前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化
螺丝钉tina2 小时前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
小天源3 小时前
智叟云集系统 · 架构与职责分层
服务器·前端·数据库
Highcharts.js5 小时前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格
薛定谔的猫-菜鸟程序员5 小时前
Electron开发超详细教程(从入门到放弃)
前端·javascript·electron
最强小杰5 小时前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
考研保研资料分享5 小时前
2022环境工程保研北师大:三校专业追问、论文贡献与择校复盘
面试
静水leo6 小时前
使用 Whistle 拦截接口并模拟后端响应
前端