JavaScript函数闭包解析
一、什么是闭包
JavaScript中的函数闭包是指函数可以访问其父级作用域中的变量,即使函数在父级作用域外被调用。闭包可以获取和修改其父级作用域中的变量,即使父级作用域已经被销毁。
在JavaScript中,当一个函数被定义时,它会创建一个闭包。闭包包含函数中使用的任何变量,并允许函数在父级作用域中访问这些变量。
闭包的一个常见用例是创建私有变量。通过使用闭包,在函数内部定义的变量可以在函数外部是不可访问的,从而实现了封装和信息隐藏。
以下是一个简单的例子,展示了如何使用闭包创建一个私有计数器:
function createCounter() {let count = 0;function increment() {count++;console.log(count);}return increment;
}const counter = createCounter();
counter(); // 输出: 1
counter(); // 输出: 2
在上面的例子中,createCounter函数返回了一个内部函数increment。increment函数可以访问并修改createCounter函数中的count变量,即使createCounter函数已经执行完毕。每次调用counter函数时,count的值会增加并被打印出来。
这是因为increment函数形成了一个闭包,它可以访问其父级作用域中的变量。在这个例子中,count变量就是一个闭包变量。
二、观察闭包
在JavaScript中,可以通过观察函数闭包来了解函数的作用域和变量的生命周期。以下是一些观察函数闭包的方法:
1.使用console.log()输出函数闭包:可以在函数内部使用console.log()输出函数内的变量,从而观察函数闭包。例如:
function outer() {var outerVar = "I'm in outer function";function inner() {var innerVar = "I'm in inner function";console.log(outerVar);console.log(innerVar);}return inner;
}var innerFunc = outer();
innerFunc(); // 输出 "I'm in outer function" 和 "I'm in inner function"
2.使用debugger调试函数闭包:可以在函数内部使用debugger关键字设置断点,然后使用开发者工具的调试功能观察函数闭包的变量。例如:
function outer() {var outerVar = "I'm in outer function";function inner() {var innerVar = "I'm in inner function";debugger; // 设置断点console.log(outerVar);console.log(innerVar);}return inner;
}var innerFunc = outer();
innerFunc(); // 在开发者工具中观察函数闭包的变量
3.使用闭包返回函数的属性值:可以通过闭包将函数内的变量返回为函数属性,然后在外部访问该函数属性。例如:
function outer() {var outerVar = "I'm in outer function";function inner() {var innerVar = "I'm in inner function";console.log(outerVar);console.log(innerVar);}inner.outerVar = outerVar; // 通过闭包将outerVar返回为inner函数的属性return inner;
}var innerFunc = outer();
console.log(innerFunc.outerVar); // 输出 "I'm in outer function"
三、闭包的用途
闭包是JavaScript中非常有用的一种特性,它的主要用途有以下几个方面:
-
封装变量:闭包可以将变量封装起来,使其在函数外部无法直接访问,只能通过闭包内部的函数来访问和修改。这样可以保护变量的安全性,避免其他代码的误操作。
-
实现私有变量和私有方法:由于闭包的封装性,可以利用闭包实现类似于面向对象中的私有变量和私有方法的效果。外部无法直接访问和修改闭包内部的变量和方法,只能通过闭包内部提供的公共接口来操作。
-
记忆上下文:闭包可以记住其创建时的上下文环境,即使创建闭包的函数已经执行完毕,闭包仍然可以访问到当时的变量和参数。这种特性可以用于实现一些需要记住状态的功能,比如计数器、缓存等。
-
实现函数柯里化:柯里化(Currying)是一种将多个参数的函数转换为一系列单参数函数的技术。通过闭包,可以实现函数柯里化,将函数的部分参数先传入,返回一个新的函数,后续再传入其他参数。这样可以方便地复用函数和传入不同的参数组合。
-
模块化开发:闭包可以用于实现模块化开发,在一个函数内部定义多个变量和方法,并将其返回,供外部作为一个整体使用。这样可以避免全局命名冲突,提高代码的可维护性和重用性。
闭包在JavaScript中的用途是非常广泛的,可以实现很多有意思的功能和技巧。但是过度使用闭包可能会导致内存泄漏的问题,所以在使用闭包时需要注意内存管理。
四、闭包代码示例
下面是几个使用闭包的示例代码:
1.封装变量:
function createCounter() {let count = 0;return function() {return ++count;}
}const counter = createCounter();
console.log(counter()); // 输出:1
console.log(counter()); // 输出:2
2.实现私有变量和私有方法:
function createPerson() {let name = "John";function changeName(newName) {name = newName;}function getName() {return name;}return {changeName,getName};
}const person = createPerson();
console.log(person.getName()); // 输出:John
person.changeName("Alice");
console.log(person.getName()); // 输出:Alice
console.log(person.name); // 输出:undefined
3.记忆上下文:
function createCalculator() {let result = 0;return {add: function(num) {result += num;},subtract: function(num) {result -= num;},getResult: function() {return result;}};
}const calculator = createCalculator();
calculator.add(5);
calculator.subtract(3);
console.log(calculator.getResult()); // 输出:2
4.实现函数柯里化:
function add(x) {return function(y) {return x + y;}
}const add5 = add(5);
console.log(add5(3)); // 输出:8
console.log(add5(7)); // 输出:12
5.模块化开发:
const module = (function() {let privateData = "Private";function privateMethod() {console.log("Private method");}return {publicMethod: function() {console.log("Public method");},getPrivateData: function() {return privateData;}};
})();module.publicMethod(); // 输出:Public method
console.log(module.getPrivateData()); // 输出:Private
console.log(module.privateData); // 输出:undefined
这些示例代码展示了闭包的不同用途,通过使用闭包可以实现封装、保护、记忆状态、柯里化和模块化等功能。
相关文章:
JavaScript函数闭包解析
一、什么是闭包 JavaScript中的函数闭包是指函数可以访问其父级作用域中的变量,即使函数在父级作用域外被调用。闭包可以获取和修改其父级作用域中的变量,即使父级作用域已经被销毁。 在JavaScript中,当一个函数被定义时,它会创…...
STM32MP135裸机编程:使用软件触发硬件复位
0 参考资料 STM32MP13xx参考手册.pdf 1 使用寄存器实现软件复位 1.1 复位电路概述 重点关注下面标红的路线: 通过这条路线可以清楚看到,我们可以通过设置RCC_MP_GRSTCSETR寄存器让RPCTL(复位脉冲控制器)给NRST(硬件复…...
【饼图交通方式】用ECharts的graphic配置打造个性化
利用ECharts的graphic配置打造个性化图表 内容概要 ECharts是一款强大的数据可视化工具,它提供了丰富的配置选项来定制图表。本文将重点介绍graphic配置的使用,展示如何通过在饼图中添加个性化的图形元素,例如中心图像,来增强图…...
大模型学习笔记3【大模型】LLaMA学习笔记
文章目录 学习内容LLaMALLaMA模型结构LLaMA下载和使用好用的开源项目[Chinese-Alpaca](https://github.com/ymcui/Chinese-LLaMA-Alpaca)Chinese-Alpaca使用量化评估 学习内容 完整学习LLaMA LLaMA 2023年2月,由FaceBook公开了LLaMA,包含7B࿰…...
工程师 - 什么是SMP
什么是 SMP(对称多处理)? What is SMP (symmetric multiprocessing)? 对称多处理(SMP,symmetric multiprocessing)是由多个处理器完成的计算机处理过程,这些处理器共享一个操作系统࿰…...
Webpack: 并行构建
概述 受限于 Node.js 的单线程架构,原生 Webpack 对所有资源文件做的所有解析、转译、合并操作本质上都是在同一个线程内串行执行,CPU 利用率极低,因此,理所当然地,社区出现了一些以多进程方式运行 Webpack࿰…...
Vue的介绍与使用
1.Vue的介绍 内容讲解 【1】Vue介绍 1.vue属于一个前端框架,底层使用原生js编写的。主要用来进行前端和后台服务器之间的一个交互。 2.Vue是一套构建用户界面的渐进式前端框架。 “渐进式框架”简单的来说你可以将Vue作为你的应用一部分嵌入其中,代理…...
MYSQL双主双从,使用Keepalived双机热备+LVS高可用群集
MYSQL双主双从,使用Keepalived双机热备LVS高可用群集 文档只记录KeepalivedLVSmysql主从,不包含检验,如需检验,请自行添加web服务器 一、IP规划 服务器IP备注master1192.168.100.131master2的从master2192.168.100.132maste…...
9.计算机视觉—目标检测
目录 1.物体检测边缘框目标检测数据集总结边缘框代码实现2.锚框:目标检测的一种方法IoU—交并比赋予锚框标号使用非极大值抑制(NMS)输出总结代码实现1.物体检测 边缘框 一个边缘框可以通过四个数字定义 (左上x,左上y),(右下x,右下y)(左上x,左上y,宽,高)(中间x,中间y…...
构造函数深入理解
目录 构造函数构造函数体赋值初始化列表初始化列表格式初始化列表的意义以及注意点const修饰的成员变量初始化对象成员具体初始化的地方缺省值存在的意义例子1例子2 初始化与赋值引用成员变量的初始化注意点1注意点2我的疑惑 自定义类型成员初始化例子1例子2例子3例子4 初始化列…...
Rocky Linux 9 快速安装docker 教程
前述 CentOS 7系统将于2024年06月30日停止维护服务。CentOS官方不再提供CentOS 及后续版本,不再支持新的软件和补丁更新。CentOS用户现有业务随时面临宕机和安全风险,并无法确保及时恢复。由于 CentOS Stream 相对不稳定,刚好在寻找平替系统…...
go语言并发编程1-Gouroutine
参考文档:www.topgoer.com 使用方法 直接包装成函数,go关键字触发即可 注意事项 1 main方法结束后,main方法内启动的子协程会立即结束,无论是否执行完毕; 启动多个groutine 使用sync包的WaitGroup来控制…...
Sylar服务器框架——Http模块
1、http.h 定义了HttpMethod和HttpStatus /* Request Methods */ #define HTTP_METHOD_MAP(XX) \XX(0, DELETE, DELETE) \XX(1, GET, GET) \XX(2, HEAD, HEAD) \XX(3, POST, POST) \XX(4, PUT, …...
7km远距离WiFi实时图传模块,无人机海上无线传输方案,飞睿智能WiFi MESH自组网技术
在浩瀚无垠的海洋上,无人机正在开启一场前所未有的技术创新。它们不再只是天空的舞者,更是海洋的守望者,为我们带来前所未有的视野和数据。而这一切的背后,都离不开一项创新性的技术——飞睿智能远距离WiFi实时图传模块与无线Mesh…...
2024年上半年网络工程师下午真题及答案解析
试题一(20分) 某高校网络拓扑如下图所示,两校区核心(CORE-1、CORE-2),出口防火墙(NGFW-1、NGFW-2)通过校区间光缆互联,配置OSPF实现全校路由收敛,两校区相距40km。两校区默认由本地…...
Jmeter下载、安装及配置
1 Jmeter介绍 Jmeter是进行负载测试的工具,可以在任何支持Java虚拟机环境的平台上运行,比如Windows、Linux、Mac。 Jmeter模拟一组用户向目标服务器发送请求,并统计目标服务器的性能信息,比如CPU、memory usage。 2 Jmeter下载 …...
掌握高效实用的VS调试技巧
🔥 个人主页:大耳朵土土垚 1.编程常见的错误 1.1编译型错误 编程编译型错误是指在编译代码时发现的错误。编译器在编译过程中会检查代码是否符合语法规范和语义要求,如果发现错误会产生编译错误。 直接看错误提示信息(双击&#…...
实验2 字符及字符串输入输出与分支程序设计实验
字符及字符串输入输出 从键盘输入两个一位十进制数,计算这两个数之和,并将结果在屏幕上显示出来。 分支程序设计 从键盘输入一字符,判断该字符是小写字母、大写字母、数字或者其他字符。若输入为小写字母,显示“You Input a Lo…...
docker容器间网络仿真工具-pumba
docker-tc&pumba docker-tc:docker-tc项目仓库 pumba:pumba项目仓库 这两个项目理论上都可以实现对容器间的网络环境进行各种模拟干预,包括延迟,丢包,带宽限制等。 但是我在实际使用时,发现docker-tc这个工具在进行网络进行模…...
A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用
A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用 1 该驱动函数预览1.11 HAL_PCD_SOFCallback1.12 HAL_PCD_ResetCallback1.13 HAL_PCD_SuspendCallback1.14 HAL_PCD_ResumeCallback1.15 HAL_PCD_ISOOUTIncompleteCallback1.16 HAL_PCD_ISOINIncompleteCallbac…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
