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

JavaScript函数闭包解析

一、什么是闭包

JavaScript中的函数闭包是指函数可以访问其父级作用域中的变量,即使函数在父级作用域外被调用。闭包可以获取和修改其父级作用域中的变量,即使父级作用域已经被销毁。

在JavaScript中,当一个函数被定义时,它会创建一个闭包。闭包包含函数中使用的任何变量,并允许函数在父级作用域中访问这些变量。

闭包的一个常见用例是创建私有变量。通过使用闭包,在函数内部定义的变量可以在函数外部是不可访问的,从而实现了封装和信息隐藏。

以下是一个简单的例子,展示了如何使用闭包创建一个私有计数器:

function createCounter() {let count = 0;function increment() {count++;console.log(count);}return increment;
}const counter = createCounter();
counter(); // 输出: 1
counter(); // 输出: 2

在上面的例子中,createCounter函数返回了一个内部函数incrementincrement函数可以访问并修改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中非常有用的一种特性,它的主要用途有以下几个方面:

  1. 封装变量:闭包可以将变量封装起来,使其在函数外部无法直接访问,只能通过闭包内部的函数来访问和修改。这样可以保护变量的安全性,避免其他代码的误操作。

  2. 实现私有变量和私有方法:由于闭包的封装性,可以利用闭包实现类似于面向对象中的私有变量和私有方法的效果。外部无法直接访问和修改闭包内部的变量和方法,只能通过闭包内部提供的公共接口来操作。

  3. 记忆上下文:闭包可以记住其创建时的上下文环境,即使创建闭包的函数已经执行完毕,闭包仍然可以访问到当时的变量和参数。这种特性可以用于实现一些需要记住状态的功能,比如计数器、缓存等。

  4. 实现函数柯里化:柯里化(Currying)是一种将多个参数的函数转换为一系列单参数函数的技术。通过闭包,可以实现函数柯里化,将函数的部分参数先传入,返回一个新的函数,后续再传入其他参数。这样可以方便地复用函数和传入不同的参数组合。

  5. 模块化开发:闭包可以用于实现模块化开发,在一个函数内部定义多个变量和方法,并将其返回,供外部作为一个整体使用。这样可以避免全局命名冲突,提高代码的可维护性和重用性。

闭包在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&#xff0…...

工程师 - 什么是SMP

什么是 SMP(对称多处理)? What is SMP (symmetric multiprocessing)? 对称多处理(SMP,symmetric multiprocessing)是由多个处理器完成的计算机处理过程,这些处理器共享一个操作系统&#xff0…...

Webpack: 并行构建

概述 受限于 Node.js 的单线程架构,原生 Webpack 对所有资源文件做的所有解析、转译、合并操作本质上都是在同一个线程内串行执行,CPU 利用率极低,因此,理所当然地,社区出现了一些以多进程方式运行 Webpack&#xff0…...

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来控制&#xf…...

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…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

【Oracle APEX开发小技巧12】

有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如&#xff1a…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)​现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...