【前端每天一题】第 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 题:前端性能优化(重排/重绘、懒加载、打包优化)

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

相关推荐
wuhen_n2 小时前
JavaScript内置数据结构
开发语言·前端·javascript·数据结构
大鱼前端2 小时前
为什么我说CSS-in-JS是前端“最佳”的糟粕设计?
前端
不爱吃糖的程序媛2 小时前
Capacitor:跨平台Web原生应用开发利器,现已全面适配鸿蒙
前端·华为·harmonyos
AC赳赳老秦2 小时前
2026国产算力新周期:DeepSeek实战适配英伟达H200,引领大模型训练效率跃升
大数据·前端·人工智能·算法·tidb·memcache·deepseek
CHU7290352 小时前
淘宝扭蛋机抽盒小程序前端功能解析:解锁趣味抽盒新体验
前端·小程序
-凌凌漆-2 小时前
【npm】npm的-D选项介绍
前端·npm·node.js
鹿心肺语2 小时前
前端HTML转PDF的两种主流方案深度解析
前端·javascript
海石3 小时前
去到比北方更北的地方—2025年终总结
前端·ai编程·年终总结
一个懒人懒人3 小时前
Promise async/await与fetch的概念
前端·javascript·html
Mintopia3 小时前
Web 安全与反编译源码下的权限设计:构筑前后端一致的防护体系
前端·安全