首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >面试官一句话,暴露了我对js闭包的理解

面试官一句话,暴露了我对js闭包的理解

作者头像
代码简单说
发布2026-06-16 14:09:47
发布2026-06-16 14:09:47
400
举报
文章被收录于专栏:代码简单说代码简单说
面试官一句话,暴露了我对js闭包的理解

在这里插入图片描述
在这里插入图片描述

昨天去一家公司面试,原本信心满满 一切进展得很顺利。直到面试官抛出一个问题:“能不能用闭包实现一个简单的计数器?”

听起来是个很基础的考题,我胸有成竹地写出了以下代码:

代码语言:javascript
复制
function createCounter() {
  let count = 0;
  return function () {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 2

面试官点了点头,说:“这没问题,那如果加上异步操作呢?比如,延迟打印计数器的值会发生什么?”

我稍微一愣,连忙补充代码:

代码语言:javascript
复制
for (var i = 1; i <= 3; i++) {
  setTimeout(function () {
    console.log(`计数器值是: ${i}`);
  }, i * 1000);
}

结果输出却全是 “计数器值是: 4”。面试官笑着问:“你知道为什么吗?”这一刻,我意识到闭包并没有我想象得那么简单。


什么是闭包?

闭包是指 函数可以记住它定义时的词法作用域,即使这个函数是在词法作用域之外执行的。简单说,闭包让你能访问函数外部的变量。

闭包有两个关键点:

  1. 函数嵌套:内部函数可以访问外部函数的变量。
  2. 变量持久化:外部函数执行完后,它的变量不会被释放,而是由内部函数继续引用。

闭包的坑:我为什么答错了?

回到我的代码,问题出在 for 循环和 setTimeout 的结合上。

代码语言:javascript
复制
for (var i = 1; i <= 3; i++) {
  setTimeout(function () {
    console.log(`计数器值是: ${i}`);
  }, i * 1000);
}

setTimeout 中的回调函数形成了闭包,但它捕获的是变量 i引用。由于 var 定义的变量是 函数作用域,所以 for 循环结束时,i 的最终值是 4。所有的回调函数都访问同一个 i,因此输出一致。


问题的解决方法
方法一:使用 IIFE(立即执行函数表达式)

我在面试中赶紧调整代码,通过 IIFE 将每次循环的 i 传递进去,并锁定值:

代码语言:javascript
复制
for (var i = 1; i <= 3; i++) {
  (function (currentI) {
    setTimeout(function () {
      console.log(`计数器值是: ${currentI}`);
    }, currentI * 1000);
  })(i);
}

这样每次 currentI 的值都是独立的,最终输出:

代码语言:javascript
复制
计数器值是: 1
计数器值是: 2
计数器值是: 3
方法二:用 let 替代 var

幸好面试官没有让我死磕 IIFE,他提醒说 ES6 的块级作用域更优雅。于是我改用 let

代码语言:javascript
复制
for (let i = 1; i <= 3; i++) {
  setTimeout(function () {
    console.log(`计数器值是: ${i}`);
  }, i * 1000);
}

let 会为每次循环创建一个新的块级作用域,天然避免了闭包的引用问题。


面试后我的反思

闭包的问题不仅仅是记住它的定义,而是要理解它在各种场景下的表现。比如,异步操作、变量共享等问题,往往会暴露我们对闭包的理解深度。

牢记闭包的两个陷阱:
  1. 变量引用而非值:闭包中的变量如果是引用类型,可能导致预期外的共享。
  2. 延迟执行:异步代码中的闭包容易捕获到变量的最终值,而不是当前值。

总结

面试结束后,我在闭包上深挖了一下才发现,掌握它不仅对写代码有帮助,也是衡量一个开发者功力的关键指标。闭包虽然是 js 的“老生常谈”,但真正理解透彻的人却不多。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 面试官一句话,暴露了我对js闭包的理解
  • 什么是闭包?
  • 闭包的坑:我为什么答错了?
  • 问题的解决方法
    • 方法一:使用 IIFE(立即执行函数表达式)
    • 方法二:用 let 替代 var
  • 面试后我的反思
    • 牢记闭包的两个陷阱:
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档