前端JavaScript篇之对闭包的理解

news2024/9/24 7:18:54

目录

  • 对闭包的理解
    • 用途
    • 循环中使用闭包解决 var 定义函数的问题


对闭包的理解

闭包是指一个函数能够访问并操作其词法作用域(定义时所在的作用域)之外的变量的能力。它可以通过在一个函数内部创建另一个函数来实现。内部函数可以访问外部函数的局部变量、参数和其他内部函数,即使外部函数已经执行结束,这些变量仍然可以被内部函数引用。

用途

闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量。这种方法可以用来创建私有变量。

function outerFunction() {
  var privateVariable = 'I am a private variable'

  function innerFunction() {
    console.log(privateVariable) // 可以访问函数内部的变量
  }

  return innerFunction // 返回内部函数
}

var closure = outerFunction() // 创建闭包
closure() // 在外部访问函数内部变量,输出:I am a private variable

请添加图片描述

在上述代码中,我们定义了一个外部函数 outerFunction,它内部有一个私有变量 privateVariable。然后,我们在外部函数中定义了一个内部函数 innerFunction,内部函数可以访问和使用外部函数中的私有变量。最后,我们返回内部函数,并将其赋值给变量 closure。当我们调用 closure() 时,内部函数被执行,并输出了 privateVariable 的值。

闭包的第二个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中。因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。

function outerFunction() {
  var outerVariable = 'I am from outer function'

  function innerFunction() {
    console.log(outerVariable) // 访问已经运行结束的函数的变量
  }

  return innerFunction // 返回内部函数
}

var closure = outerFunction() // 创建闭包
closure() // 在外部访问已经运行结束的函数的变量,输出:I am from outer function

请添加图片描述

在上述代码中,我们定义了一个外部函数 outerFunction,它内部有一个变量 outerVariable。然后,我们在外部函数中定义了一个内部函数 innerFunction,内部函数可以访问和使用已经运行结束的函数的变量。最后,我们返回内部函数,并将其赋值给变量 closure。当我们调用 closure() 时,内部函数被执行,并输出了 outerVariable 的值。

综上所述,闭包的用途包括保护变量、记住状态、实现模块化、函数柯里化以及延迟执行和回调。通过合理地运用闭包,我们可以写出更加灵活、模块化和易于维护的JavaScript代码。

循环中使用闭包解决 var 定义函数的问题

当在循环中使用 var 关键字定义函数时,常常会遇到闭包问题。具体而言,闭包会共享同一个循环变量,导致函数在运行时使用的变量值不符合预期。为了解决这个问题,可以使用闭包和不同的解决方法。

以下是解决该问题的三种常见方法的详细解释和示例代码。

方法一:使用函数作用域和闭包

使用函数作用域和闭包的方法来解决循环中使用 var 定义函数的问题。具体操作是将函数定义在单独的作用域内,以创建一个新的闭包环境,使每个函数拥有独立的变量。

for (var i = 0; i < 5; i++) {
  ;(function () {
    var index = i // 创建新的变量,并将循环变量的值赋给它
    setTimeout(function () {
      console.log(index)
    }, 1000 * index)
  })()
}

请添加图片描述

在上述代码中,我们将匿名函数 (function() { ... })() 用于创建新的作用域。在这个作用域中,我们创建了一个新的变量 index,并将循环变量 i 的值赋给它。每次循环迭代都会创建一个独立的 index 变量,以避免共享循环变量导致的问题。

在闭包函数内部,我们使用 setTimeout 函数设置一个定时器,在延迟时间之后打印当前的 index 值。通过给定的延迟时间 1000 * index,我们可以按顺序输出 04 的值。

方法二:使用立即执行函数表达式和闭包

使用立即执行函数表达式(IIFE)和闭包来解决循环中使用 var 定义函数的问题。每次循环迭代时,都会创建一个新的闭包作用域,确保每个闭包函数拥有独立的变量。

for (var i = 0; i < 5; i++) {
  ;(function (index) {
    setTimeout(function () {
      console.log(index)
    }, 1000 * index)
  })(i)
}

在上述代码中,我们定义了一个立即执行的匿名函数 (function(index) { ... })(i),并将循环变量 i 作为参数传递给该函数。通过这种方式,在每次循环迭代中,都会创建一个新的闭包作用域,并将 index 参数的值绑定到闭包内部。因此,每个闭包函数都引用着自己独立的 index 变量,避免了共享循环变量的问题。

在闭包函数内部,我们使用 setTimeout 函数设置一个定时器,在延迟时间之后打印当前的 index 值。通过给定的延迟时间 1000 * index,我们可以按顺序输出 04 的值。

方法三:使用 let 关键字声明循环变量
使用 let 关键字来声明循环变量。let 声明的变量具有块级作用域,在每次循环迭代时都会创建一个新的变量实例,从而避免了变量共享的问题。

以下是使用 let 声明循环变量解决循环中使用 var 定义函数的问题的示例代码:

for (let i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i)
  }, 1000 * i)
}

在上述代码中,我们使用 let 关键字来声明循环变量 i。由于每次循环迭代都会创建一个新的块级作用域,每个定时器回调函数都能够访问到自己独立的 i 变量,而不会受到外部循环的影响。

这三种方法都可以解决循环中使用 var 定义函数时的闭包问题。具体使用哪种方法取决于个人偏好和代码的情况。方法一适用于需要在闭包内部使用变量的复杂情况,而方法二和方法三更简洁明了,适用于简单的循环。

持续学习总结记录中,回顾一下上面的内容:
闭包是指函数可以访问其外部函数作用域中的变量,并且可以在其生命周期内保持对这些变量的引用。换句话说,闭包允许函数访问定义在自己外部的作用域中的变量,即使这些变量在外部函数执行完毕后仍然可以被访问和操作。
通俗地说,闭包就像是一个记忆力很好的函数,它可以记住并访问在它诞生时的环境中的东西。这意味着即使外部函数已经执行完毕,闭包仍然可以使用外部函数中的变量值。这种特性使得我们可以在JavaScript中实现很多有趣和灵活的编程技巧,比如私有变量、模块化等。
通过使用闭包,我们可以创建更加灵活和复用的函数,同时能够保护一些内部状态不被外部轻易篡改。但需要小心使用闭包,因为过度或不正确地使用闭包可能导致内存泄漏或意外的变量共享问题。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python算法题集_两数相加

Python算法题集_两数相加 题2&#xff1a;两数相加1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【直接相加】2) 改进版一【对齐链表】3) 改进版二【数组求和】 4. 最优算法 本文为Python算法题集之一的代码示例 题2&#xff1a;两数相加 1.…

相机图像质量研究(10)常见问题总结:光学结构对成像的影响--光圈

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

Quicker读取浏览器的书签(包括firefox火狐)

从edge换了火狐&#xff0c;但是quicker不能读取本地的bookmarks文件了&#xff0c;就研究了一下。 方法1&#xff1a;读取本地Bookmarks文件&#xff08;仅谷歌内核浏览器&#xff09; 谷歌内核的浏览器本地会有Bookmarks文件&#xff0c;放了所有的书签数据&#xff0c;直接…

我的docker随笔43:问答平台answer部署

本文介绍开源问答社区平台Answer的容器化部署。 起因 笔者一直想搭建一个类似stack overflower这样的平台&#xff0c;自使用了Typora&#xff0c;就正式全面用MarkdownTyporagit来积累自己的个人知识库&#xff0c;但没有做到web化&#xff0c;现在也还在探索更好的方法。 无…

MyBatisPlus基础操作之增删改查

目录 一、基本使用 1.1 插入数据 1.2 删除操作 1.3 更新操作 二、条件构造器Wrapper 2.1 常用AbstractWrapper方法 2.1.1 示例一 2.2.2 示例二 2.2.3 示例三 2.2 常用QueryWrapper方法 2.2.1 示例一 2.2.2 示例二 2.2.3 示例三&#xff08;常用&#xff09; 2.3 常…

PgSQL技术内幕 - case when表达式实现机制

PgSQL技术内幕 - case when表达式实现机制 CASE表达式如同 C语言中的if/else语句一样&#xff0c;为SQL添加了条件逻辑处理能力&#xff0c;可以根据不同条件返回不同结果。PgSQL支持两种语法&#xff1a;简单表达式和搜索表达式。 1、搜索表达式 语法如下&#xff1a; CASE WH…

android studio下开发flutter

文章目录 1. 配置环境 https://flutter.cn/docs/get-started/install2. android studio下开发flutter 1. 配置环境 https://flutter.cn/docs/get-started/install 2. android studio下开发flutter 打开Android Studio -> File -> Settings -> Plugins 搜索Dart插件 …

java_error_in_pycharm.hprof文件是什么?能删除吗?

java_error_in_pycharm.hprof文件是什么&#xff1f;能删除吗&#xff1f; &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333;hprof格式文件介绍&#x1f333;&#x1f333;java_error_in_pycharm.hprof文件什么情况下能删除&#x1f333;&…

简化版SpringMVC

简化版SpringMVC web.xml xml version"1.0" encoding"UTF-8"?> <web-app version"2.5" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation&quo…

科技王座“座次变更”:英伟达超越亚马逊在即,距离谷歌也不远

英伟达的市值即将超过亚马逊&#xff0c;为二十年来首次。 截至2月7日收盘&#xff0c;英伟达市值达到1.73万亿美元&#xff0c;逼近亚马逊1.77万亿美元的市值&#xff0c;距离谷歌1.82万亿美元的市值也不远。 对人工智能的热情推升英伟达的股价去年以来一路飙涨&#xff0c;受…

【开源】基于JAVA+Vue+SpringBoot的新能源电池回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…

nginx登录用户验证配置

我们的nginx端口一般都是对外开放的&#xff0c;所以有一定程度上有被别人扫描的风险&#xff0c;所以为了减少被扫描的风险&#xff0c;我们可以配置一个nginx的用户登录验证&#xff1b; 用户验证登录需要nginx的一个模块&#xff1a;ngx_http_auth_basic_module 我们使用…

MySQL 时间索引的选择

背景 MySQL 在使用过程中经常会对时间加索引&#xff0c;方便进行时间范围的查询&#xff0c;常见的时间类型有 data、datetime、long、timestamp 等&#xff0c;在此分析下这几种时间类型的索引大小&#xff0c;以找到比较合适的时间类型。 时间类型对比 常用的索引类型是 …

SolidWorks学习笔记——入门知识2

目录 建出第一个模型 1、建立草图 2、选取中心线 3、草图绘制 4、拉伸 特征的显示与隐藏 改变特征名称 5、外观 6、渲染 建出第一个模型 1、建立草图 图1 建立草图 按需要选择基准面。 2、选取中心线 图2 选取中心线 3、草图绘制 以对称图形举例&#xff0c;先画出…

市场复盘总结 20240207

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率中 75% 最常用…

优化 IT 支出和消除浪费的 8 种主要方法

不懈追求最佳 IT 支出对于任何组织的长期可持续发展和成功都至关重要。在这个技术快速进步的时代&#xff0c;您必须做出明智的决策&#xff0c;消除浪费&#xff0c;同时最大限度地提高技术投资的价值。 从进行 IT 成本分析到采用敏捷预算和技术标准化&#xff0c;这些策略对…

算法学习——LeetCode力扣链表篇2

算法学习——LeetCode力扣链表篇2 24. 两两交换链表中的节点 24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&…

C语言特殊指针

1 野指针 概念&#xff1a;指向一块未知区域的指针&#xff0c;被称为野指针。野指针是危险的。 危害&#xff1a; 引用野指针&#xff0c;相当于访问了非法的内存&#xff0c;常常会导致段错误&#xff08;segmentation fault&#xff09;引用野指针&#xff0c;可能会破坏系…

CRNN介绍:用于识别图中文本的深度学习模型

CRNN&#xff1a;用于识别图中文本的深度学习模型 CRNN介绍&#xff1a;用于识别图中文本的深度学习模型CRNN的结构组成部分工作原理 CRNN结构分析卷积层&#xff08;Convolutional Layers&#xff09;递归层&#xff08;Recurrent Layers&#xff09;转录层&#xff08;Transc…

day7(2024/2/8)

mainui.h(第二个界面) #ifndef MAINUI_H #define MAINUI_H#include <QWidget>namespace Ui { class MainUi; }class MainUi : public QWidget {Q_OBJECTpublic:explicit MainUi(QWidget *parent nullptr);~MainUi();public slots:void main_ui();private:Ui::MainUi *u…