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

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

相关推荐
网络点点滴几秒前
前端与后端的区别与联系
前端
EnCi Zheng25 分钟前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen29 分钟前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技30 分钟前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人41 分钟前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实41 分钟前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha1 小时前
三目运算符
linux·服务器·前端
晓晨的博客1 小时前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
donecoding1 小时前
别再让 pnpm 跟着 nvm 跑了!独立安装终极指南
前端·node.js·前端工程化