详细讲一下什么是闭包,为什么会产生闭包,闭包会导致什么,闭包可以帮助我们在开发中干什么

 1. 什么是闭包?

 简单理解:闭包就是一个函数能够记住并访问它的外部变量,即使这个函数在其他地方执行

 专业定义:闭包是一个函数以及其周围状态(词法环境)的引用的组合

2. 基本闭包示例

function createCounter() {let count = 0  // 这个变量被内部函数所引用,形成闭包return function() {count++  // 内部函数可以访问外部函数的变量console.log(count)}
}const counter = createCounter()
counter()  // 输出: 1
counter()  // 输出: 2
// 解释:即使 createCounter 已经执行完毕,但 count 变量仍然存在且能被访问
// 因为返回的函数形成了一个闭包,保持着对 count 的引用

 3. 闭包的实际应用场景

3.1 数据私有化

function createBankAccount(initialBalance) {let balance = initialBalance  // 私有变量return {// 只提供特定的方法来访问和修改余额getBalance: function() {return balance},deposit: function(amount) {balance += amountreturn balance},withdraw: function(amount) {if (amount > balance) {return '余额不足'}balance -= amountreturn balance}}
}const account = createBankAccount(1000)
console.log(account.getBalance())  // 1000
account.deposit(500)  // 1500
account.withdraw(200)  // 1300
// account.balance  // undefined,无法直接访问 balance

3.2 函数工厂(创建具有特定行为的函数)

function multiply(x) {return function(y) {return x * y}
}const multiplyByTwo = multiply(2)
const multiplyByFive = multiply(5)console.log(multiplyByTwo(3))  // 6
console.log(multiplyByFive(3))  // 15

3.3 事件处理和回调

function setupHandler() {let clickCount = 0// 这个函数形成闭包,记住了 clickCountreturn function handler() {clickCount++console.log(`按钮被点击了 ${clickCount} 次`)}
}const handleClick = setupHandler()
// 每次点击都能正确显示点击次数,因为 clickCount 被保存在闭包中

4. 闭包可能导致的问题

4.1 内存泄漏

// 4.1 内存泄漏
function createLeak() {const largeData = new Array(1000000)  // 大量数据return function() {// 使用了外部变量,导致 largeData 无法被垃圾回收console.log(largeData.length)}
}

4.2 循环中的常见错误

// 4.2 循环中的常见错误
// 错误示例
for(var i = 0; i < 3; i++) {setTimeout(function() {console.log(i)  // 会输出三次 3}, 1000)
}// 正确做法
for(let i = 0; i < 3; i++) {setTimeout(function() {console.log(i)  // 会输出 0, 1, 2}, 1000)
}

5.隆重介绍闭包在实际开发中的一些重要应用

1. 防抖 (Debounce)

// 1. 防抖 (Debounce)
// 作用:将多次连续的函数调用合并成一次,常用于搜索框输入、窗口调整等
function debounce(fn, delay) {let timer = null  // 使用闭包保存定时器return function(...args) {// 每次触发时,清除之前的定时器if (timer) clearTimeout(timer)// 设置新的定时器timer = setTimeout(() => {fn.apply(this, args)}, delay)}
}// 防抖使用示例
const handleSearch = debounce(function(keyword) {console.log('搜索关键词:', keyword)
}, 300)// 用户快速输入时,只会在最后一次输入后300ms才执行搜索
searchInput.addEventListener('input', (e) => handleSearch(e.target.value))

2. 节流 (Throttle)

// 作用:限制函数在一定时间内只能执行一次,常用于滚动事件、按钮点击等
function throttle(fn, interval) {let lastTime = 0  // 使用闭包保存上次执行时间return function(...args) {const nowTime = Date.now()// 如果距离上次执行的时间大于间隔,则执行函数if (nowTime - lastTime >= interval) {fn.apply(this, args)lastTime = nowTime}}
}// 节流使用示例
const handleScroll = throttle(function() {console.log('页面滚动位置:', window.scrollY)
}, 200)// 滚动时每200ms最多执行一次
window.addEventListener('scroll', handleScroll)

3. 缓存函数结果 (Memoization)

// 3. 缓存函数结果 (Memoization)
// 作用:缓存计算结果,避免重复计算
function memoize(fn) {const cache = {}  // 使用闭包保存缓存return function(...args) {const key = JSON.stringify(args)if (key in cache) {console.log('从缓存中获取结果')return cache[key]}console.log('计算新的结果')const result = fn.apply(this, args)cache[key] = resultreturn result}
}// 缓存函数使用示例
const expensiveFunction = memoize((n) => {// 假设这是一个耗时的计算return new Promise(resolve => {setTimeout(() => {resolve(n * 2)}, 1000)})
})

4. 创建自增ID生成器

// 4. 创建自增ID生成器
// 作用:生成唯一ID
function createIdGenerator() {let id = 0  // 使用闭包保存idreturn function() {return ++id}
}const generateId = createIdGenerator()
console.log(generateId())  // 1
console.log(generateId())  // 2

5. 创建一次性执行的函数 (Once)

// 5. 创建一次性执行的函数 (Once)
// 作用:确保函数只执行一次,常用于初始化操作
function once(fn) {let called = false  // 使用闭包记录是否调用过let resultreturn function(...args) {if (!called) {result = fn.apply(this, args)called = true}return result}
}// 一次性函数使用示例
const initialize = once(() => {console.log('初始化操作,只执行一次')return { data: 'initialized' }
})

6. 柯里化 (Currying)

6. 柯里化 (Currying)
// 作用:将多参数函数转换为一系列单参数函数
function curry(fn) {return function curried(...args) {if (args.length >= fn.length) {return fn.apply(this, args)}return function(...moreArgs) {return curried.apply(this, args.concat(moreArgs))}}
}// 柯里化使用示例
const add = curry((a, b, c) => a + b + c)
console.log(add(1)(2)(3))  // 6
console.log(add(1, 2)(3))  // 6

总结:

1.闭包的本质是函数能够访问其定义时的作用域

2.闭包主要用于:

  • 数据私有化
  • 状态维护
  • 函数工厂
  • 回调函数

3. 闭包的优点:

  • 可以访问外部变量
  • 可以维护私有变量
  • 可以实现数据封装

4.闭包的注意事项:

  • 可能造成内存泄漏
  • 创建太多闭包可能影响性能
  • 需要注意变量作用域

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/504054.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大模型】百度千帆大模型对接LangChain使用详解

目录 一、前言 二、LangChain架构与核心组件 2.1 LangChain 核心架构 2.2 LangChain 核心组件 三、环境准备 3.1 前置准备 3.1.1 创建应用并获取apikey 3.1.2 开通付费功能 3.2 获取LangChain文档 3.3 安装LangChain依赖包 四、百度千帆大模型对接 LangChain 4.1 LL…

用Python实现简单的任务自动化

目录 1. 自动发送邮件提醒 2. 自动备份文件 3. 自动下载网页内容 总结 在现代工作和生活中,任务自动化可以极大地提高效率和准确性。Python,作为一种功能强大且易于学习的编程语言,是实现任务自动化的理想选择。本文将通过几个简单而实用的案例,展示如何用Python实现任…

用JAVA编写一个简单的小游戏

用Java语言编写一个简单的小游戏。这里是一个非常基础的猜数字小游戏的代码示例。在这个游戏中&#xff0c;程序会随机选择一个1到100之间的整数&#xff0c;玩家需要猜测这个数字是什么。每次猜测后&#xff0c;程序会告诉玩家他们猜的数字是太高了、太低了还是正确。 impor…

腾讯云AI代码助手编程挑战赛-凯撒密码解码编码器

作品简介 在CTFer选手比赛做crypto的题目时&#xff0c;一些题目需要自己去解密&#xff0c;但是解密的工具大部分在线上&#xff0c;而在比赛过程中大部分又是无网环境&#xff0c;所以根据要求做了这个工具 技术架构 python语言的tk库来完成的GUI页面设计&#xff0c;通过…

MATLAB深度学习实战文字识别

文章目录 前言视频演示效果1.DB文字定位环境配置安装教程与资源说明1.1 DB概述1.2 DB算法原理1.2.1 整体框架1.2.2 特征提取网络Resnet1.2.3 自适应阈值1.2.4 文字区域标注生成1.2.5 DB文字定位模型训练 2.CRNN文字识别2.1 CRNN概述2.2 CRNN原理2.2.1 CRNN网络架构实现2.2.2 CN…

EXCEL: (二) 常用图表

10. 图表 134-添加.删除图表元素 图表很少是一个单独的整体&#xff0c;而是由十几种元素/对象拼凑出来的。 学习图表就是学习当中各类元素的插删改。 ①图表中主要元素的定义 图表上的一个颜色就是一个系列。 横轴是分类轴&#xff0c;将每个系列都分为几类。 ②选中图…

晨辉面试抽签和评分管理系统之一:考生信息管理和编排

晨辉面试抽签和评分管理系统&#xff08;下载地址:www.chenhuisoft.cn&#xff09;是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…

c++类和对象---上

文章目录 类的介绍 类的声明 1.1 类名 1.2 成员变量 1.3 成员函数 1.4 访问权限 类的定义 2.1 成员变量的初始化 2.2 成员函数的实现 对象的创建和销毁 3.1 默认构造函数 3.2 析构函数 3.3 拷贝构造函数 3.4 对象的实例化 3.5 对象的销毁 成员访问控制 4.1 公有成员 4.2 私有…

UI自动化测试保姆级教程--pytest详解(精简易懂)

欢迎来到啊妮莫的学习小屋 别让过去的悲伤&#xff0c;毁掉当下的快乐一《借东西的小人阿莉埃蒂》 简介 pytest是一个用于Python的测试框架, 支持简单的单元测试和复杂的功能测试. 和Python自带的UnitTest框架类似, 但是相比于UnitTest更加简洁, 效率更高. 特点 非常容易上手…

关于Mac使用VSCode连接虚拟机

1. 下载插件 输入Remote - SSH下载下图两个插件。 2. 配置虚拟机信息 按图示步骤点击完成后&#xff0c;进入到虚拟主机的配置页面。 其中Host可以自定义主机名&#xff0c;HostName是虚拟机ip&#xff0c;可以通过ifconfig eth0查看ip&#xff0c;User是虚拟机的用户名。…

细说STM32F407单片机以轮询方式读写外部SRAM的方法

目录 一、实例的功能 二、工程配置 1、KEYLED 2、时钟、DEBUG、USART6、NVIC、GPIO、CodeGenerator 3、FSMC &#xff08;1&#xff09; 模式设置 &#xff08;2&#xff09; Bank 1子区3参数设置 1) NOR/PSRAM control组&#xff0c;子区控制参数 2) NOR/PSRAM timi…

Eclipse配置Tomcat服务器(最全图文详解)

前言&#xff1a; 本章使用图文讲解如何在Eclipse开发工具中配置Tomcat服务器、如何创建和启动JavaWeb工程&#xff0c;欢迎童鞋们互相交流。觉得不错可以三连订阅喔。 目标&#xff1a; 一、配置Tomcat服务器 1. 切换Eclipse视图 2. 打开菜单 3. 找到服务选项 4. 选择…

uniapp vue2版本如何设置i18n

如何设置i18n在该软件设置过语言的情况下优先选择所设置语言&#xff0c;在没有设置的情况下&#xff0c;获取本系统默认语言就&#xff0c;将系统默认语言设置为当前选择语言。 1、下载依赖&#xff1a; npm install vue-i18n --save 2、创建相关文件&#xff08;在最外层&…

QPS和TPS 的区别是什么?QPS 大了会有什么问题,怎么解决?

QPS 和 TPS 的区别是什么&#xff1f;QPS 大了会有什么问题&#xff0c;怎么解决&#xff1f; QPS&#xff08;Queries Per Second&#xff09;和 TPS&#xff08;Transactions Per Second&#xff09;都是衡量系统性能的重要指标&#xff0c;尤其是在 Web 服务、数据库和分布…

《Spring Framework实战》4:Spring Framework 文档

欢迎观看《Spring Framework实战》视频教程 概述 历史&#xff0c; 设计理念&#xff0c; 反馈&#xff0c; 开始。 核心技术 IoC 容器、事件、资源、i18n、 验证、数据绑定、类型转换、SpEL、AOP、AOT。 测试 Mock 对象、TestContext 框架、 Spring MVC 测试&#xff0c;…

经典多模态模型CLIP - 直观且详尽的解释

对比语言-图像预训练&#xff08;CLIP&#xff09;&#xff0c;这是一种创新的多模态建模策略&#xff0c;能够创建视觉和语言的联合表示。CLIP 的效果非常出色&#xff0c;可以用于构建高度特定且性能卓越的分类器&#xff0c;而无需任何训练数据。本文将深入探讨其理论基础&a…

vulnhub靶场【DC系列】之7

前言 靶机&#xff1a;DC-7&#xff0c;IP地址为192.168.10.13 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.2 都采用VMWare&#xff0c;网卡为桥接模式 对于文章中涉及到的靶场以及工具&#xff0c;我放置在网盘中&#xff0c;链接&#xff1a;https://pan.quark…

内网基础-防火墙-隧道技术

内网对抗-网络通讯篇&防火墙组策略&入站和出站规则&单层双层&C2正反向上线 关闭第一个防火墙&#xff1a; 第一个上线就走反向或者正向 第二个上线走反向&#xff08;第二个防火墙阻止入站&#xff09; 关闭第二个防火墙&#xff1a; 第一个上线就走反向&a…

BGP的local_preference本地优先级属性

一、BGP的local preference属性简介 1、local preference公认任意属性 当一条BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由属性进行比较&#xff0c;从而筛选出最佳到达目标网络的通达路径。本地优先属性&#xff0c;只在IBGP对等体之间…

从零手写线性回归模型:PyTorch 实现深度学习入门教程

系列文章目录 01-PyTorch新手必看&#xff1a;张量是什么&#xff1f;5 分钟教你快速创建张量&#xff01; 02-张量运算真简单&#xff01;PyTorch 数值计算操作完全指南 03-Numpy 还是 PyTorch&#xff1f;张量与 Numpy 的神奇转换技巧 04-揭秘数据处理神器&#xff1a;PyTor…