当前位置: 首页 > news >正文

闭包(Closure)概念与案例

**闭包(Closure)**是函数式编程和许多现代语言(尤其是 JavaScript、Python、Swift、Kotlin 等)中的核心概念。

1. 概念是什么?

闭包是一个函数,加上它被创建时所能访问的**词法作用域(lexical scope)**中的变量的引用。

简单说:

  • 一个内部函数可以访问外部函数的变量。
  • 即使外部函数已经执行完毕、返回了,内部函数依然能“记住”并使用那些外部变量。
  • 这些被“记住”的变量和内部函数一起,构成了闭包。

关键特征:

  • 词法作用域:变量的作用域在代码书写时就确定了,而不是运行时。
  • 持久化:外部函数的局部变量不会因为函数执行结束而被销毁(只要还有闭包引用它)。

2. 作用是什么?

闭包的主要作用可以概括为:

作用说明
数据私有化 / 封装让变量不被外部直接访问,只能通过特定接口操作
状态保持函数可以“记住”上一次的状态,实现有状态的函数
延迟执行 / 回调把函数和它的环境一起传递,稍后再执行时仍能访问原来的变量
工厂函数 / 函数工厂通过参数生成具有不同行为的函数
模块化在没有 class 的早期语言中模拟私有变量和模块

3. 能解决什么实际问题?

  1. 实现私有变量(真正的封装)
    在 JavaScript 中没有真正的 private 关键字(ES2022 之前),闭包是实现私有数据的经典方式。

  2. 函数记忆上一次的计算结果 / 状态
    比如计数器、节流、防抖、缓存等。

  3. 解决循环中的异步问题(经典坑)
    for循环里创建多个异步回调时,闭包可以正确捕获每次循环的值。

  4. 高阶函数与柯里化
    把多参数函数变成一系列单参数函数,或者实现部分应用(partial application)。

  5. 事件处理与回调
    点击按钮时需要访问创建时的上下文变量。

  6. 模块模式(Module Pattern)
    在早期 JS 中实现命名空间和私有成员。

4. 典型案例

案例 1:计数器(最经典)
functioncreateCounter(){letcount=0;// 私有变量returnfunction(){// 闭包count++;returncount;};}constcounter1=createCounter();constcounter2=createCounter();console.log(counter1());// 1console.log(counter1());// 2console.log(counter2());// 1 (各自独立)
案例 2:函数工厂(根据参数生成不同行为)
functionmakeMultiplier(factor){returnfunction(x){returnx*factor;};}constdouble=makeMultiplier(2);consttriple=makeMultiplier(3);console.log(double(5));// 10console.log(triple(5));// 15
案例 3:解决循环 + 异步的经典问题
// 错误写法(所有都输出 3)for(vari=0;i<3;i++){setTimeout(()=>console.log(i),100);}// 用闭包修复for(vari=0;i<3;i++){(function(j){// 立即执行函数创建闭包setTimeout(()=>console.log(j),100);})(i);}// 现代写法(let 本身就有块级作用域)for(leti=0;i<3;i++){setTimeout(()=>console.log(i),100);}
案例 4:防抖(Debounce)
functiondebounce(fn,delay){lettimer=null;returnfunction(...args){clearTimeout(timer);timer=setTimeout(()=>{fn.apply(this,args);},delay);};}consthandleSearch=debounce((keyword)=>{console.log('搜索:',keyword);},300);
案例 5:模块模式(IIFE + 闭包)
constCalculator=(function(){letresult=0;// 私有return{add(x){result+=x;returnthis;},subtract(x){result-=x;returnthis;},getResult(){returnresult;}};})();Calculator.add(10).subtract(3);console.log(Calculator.getResult());// 7

总结

闭包 = 函数 + 它诞生时的环境。

它让函数拥有“记忆力”,能够封装数据、保持状态、延迟执行,是 JavaScript 等语言实现高级抽象的重要基础。理解闭包,也就理解了作用域、生命周期和函数式编程的核心思想。

http://www.jsqmd.com/news/1393408/

相关文章:

  • 北京房山名包回收合规门店特征:实体经营+资质公示+鉴定师持证+明码标价 - 大牌科普时报
  • 9大网盘直链解析工具:一键拿到真实下载地址,从此告别限速等待
  • 【Vue知识点总结】Vue如何实现跳转页面?
  • OneNav 主题切换到底值不值得折腾?5 个玩法让书签导航页脱胎换骨
  • 文字转CAD工具text-to-cad-ui快速上手指南:3步把一句描述变成可用的3D模型
  • LLM Interview Questions and Answers Hub:100+精选问题助你轻松应对AI面试
  • 车门凹了不拆件、不刮腻子就能修平?奎屯车主在艺猫找到凹陷无痕修复的满分答案 - 生活动态圈
  • 179、LLC谐振变换器的PCB设计实战(DFA)
  • Claude Code架构解析:从代理循环到生产级安全带的AI编程伙伴
  • 一文讲透细胞通讯数据库CellChatDB:配体-受体相互作用与单细胞通讯分析实战指南
  • 一上午搬空一个网站:WebSite-Downloader 让整站离线下载不再依赖网络
  • 【风电功率预测】【多变量输入单步预测】基于LSTM的风电功率预测研究附Matlab代码
  • MulimgViewer 多图像浏览器快速上手指南:图像批量对比与拼接的终极方案
  • nano——命令行文本编辑器
  • C++ std::array:从基础容器到编译期编程的实战指南
  • 2026年重庆全博印章公司发展历程与主营项目全解析 - 起跑123
  • 深入理解Pixelarticons生成原理:React组件自动生成脚本解析
  • 180、LLC谐振变换器的PCB设计实战(Gerber输出)
  • tchMaterial-parser:三步免费下载国家中小学智慧教育平台电子课本PDF
  • 免费USB启动盘制作工具Rufus完整指南:三步快速创建可引导U盘
  • 报价写在纸上、质保拉到十年:奎屯这家店把「透明」和「保障」做进了底气 - 生活动态圈
  • 【DeepSeek Harness】从安装到使用完整指南
  • otel-cli完全指南:如何在Shell脚本中轻松发送OpenTelemetry追踪数据
  • RegRipper3.0核心功能详解:自动插件匹配与高效注册表分析技巧
  • 洛雪音乐音源实战入门:3步导入、避坑与推荐组合,一学就会
  • 鼠标光标也能随心换?聊聊 macOS 上那个叫 Mousecape 的非侵入式光标定制神器
  • 基于STM32的智能台灯毕业设计:从硬件选型到软件实现的完整方案
  • 2026年重庆全博印章市场服务口碑最新调研新闻报道 - 起跑123
  • 开发自定义终端应用?Pastel与TTY工具包的集成最佳实践
  • 当“过时“变成硬通货:读懂 Genesis Plus GX 如何把世嘉 8/16 位硬件搬进现代代码