学习 JavaScript 闭包

1. 前言

闭包是 JavaScript 中一种非常重要的概念,它允许函数访问其外部作用域中的变量,即使在函数被返回或者在其原始定义的作用域之外执行时仍然可以访问这些变量。

在讲解闭包之前我们得弄清楚下面的概念:

  1. 作用域链: JavaScript 中的作用域是通过词法作用域(也称为静态作用域)来确定的,即函数在定义时所处的作用域决定了它能够访问的变量。当一个函数被创建时,也会创建一个作用域链,其中包含了函数自身的作用域以及所有包含(外部)作用域中的变量对象。
  2. 内部函数: 在 JavaScript 中,函数可以嵌套定义,即在一个函数内部可以再定义一个函数。当内部函数被返回或者在其定义的作用域之外执行时,它既可以访问外部变量也可以访问内部变量。
  3. 引用外部变量: 当内部函数引用外部函数的变量时,JavaScript 引擎会将这些变量保存在闭包中。这意味着即使外部函数执行完毕,其内部函数仍然可以访问和操作外部函数的变量。

2. 闭包

2.1. 变量的作用域

按照常理来说,我们在上一级作用域是无法访问下一级作用域的局部变量的。例如:

function fn(){  var n = 1;  
}fn();
console.log(n); // n not defined!

在这里我们调用了 fn 函数,认为变量 n 定义后就能在外部被访问,但是我们得到了一个错误。所以正常来讲在外部是访问不了内部的局部变量的。但是闭包使得这个问题变为了可能。

2.2. 如何从外部访问局部变量

但是有时候我们确实想获取内部的局部变量该怎么办呢?首先我们在内部定义一个函数,如下:

function outer(){  var n = 1;  function inner() {console.log(n);}inner();
}outer();

运行上面的代码我们可以看到控制台会输出 1,所以内部的函数能访问内部定义的局部变量这是没有问题的!

此时如果我们将这个内部的函数交给外部,让外部来调用这个函数,那么是不是就能访问到内部的局部变量了呢?答案是可行的!

function outer(){  var n = 1;  function inner() {console.log(n);}return inner;
}let inner = outer();
inner();

运行上面的代码我们也能看到控制台输出 1,这验证了我们的猜想。

2.3. 闭包的使用场景

闭包的使用场景有很多,但凡你要传递的参数是一个函数,你就使用到了闭包。比如:

function exec(fn) {fn();
}function outer() {let n = 0;function inner() {console.log(n);}window.exec(inner);
}

由上面的代码我们可以看到 exec 函数执行了传进来的函数,在 inner 函数中我们输出了局部变量 n,所以在 exec 函数中我们访问到了 outer 函数中的局部变量。

有些时候你可能连你使用到了闭包都不知道,下面是使用闭包的例子:

let n = 0;
window.setTimeout(() => console.log(n), 1000);window.setInterval(() => console.log(n), 1000);

此外在我们常使用的防抖节流中也使用到了闭包。

2.4. 注意

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。

2.5. 思考

var name = "李华";var object = {  name : "小明",getName : function(){  return function(){  return this.name;  };}
};console.log(object.getName()()); // 李华
var name = "李华";var object = {  name : "小明",getName : function(){  var that = this;  // 闭包,保存了 this 的引用,因为 this 会变,而 that 在这不会return function(){  return that.name;  };}
};console.log(object.getName()()); // 小明

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

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

相关文章

RK3568笔记十五:触摸屏测试

若该文为原创文章,转载请注明原文出处。 使用正点原子的ATK-RK3568板子,一直在测试屏幕和视频,突然想到触摸屏测试,一直没有用过,原子给的demo跑的是QT系统,触摸功能是正常的,测试一下&#xf…

Java Arrays源码剖析

Java中有一个类Arrays,包含一些对数组操作的静态方法,本文主要就来讨论这些方法以避免重新造轮子,在需要的时候自己实现它不具备的功能。 toString Arrays的toString()方法可以方便地输出一个数组的字符串形式,以便查看。它有9个重载的方法…

MySQL的JDBC操作、pymysql操作

JDBC JDBC (Java DataBase Connectivityjava数 据库连接)是一种用于执行SQL语句的Java API。 JDBC是Java访问数据库的标准规范,可以为不同的关系型数据库提供统一访问, 它由一组用Java语言编写的接口和类组成。 JDBC需要连接驱动,驱动是两个设…

学习天机02

1.注入bean的写法 构造函数的注入 2.回答和评论 在做这个功能的时候需要理解一些概念,张三提出问题就是提问者,李四去回答张三的问题,李四就是回答者,王五去回答李四的评论,王五就是评论者。 在提供的InteractionRep…

reprod_log复现精度对比小工具

reprod_log复现精度对比小工具 主要用于对比和记录模型复现过程中的各个步骤精度对齐情况 pip 安装 pip3 install reprod_log --force-reinstall 提供的类和方法 论文复现赛 在论文复现赛中,主要用到的类如下所示。 ReprodLogger 功能:记录和保存…

MySQL免安装版安装教程

官网下载安装包 MySQL :: Download MySQL Community Server (Archived Versions) 选择mysql版本下载 安装配置MySQL 将下载完的Mysql安装包解压到指定目录 打开windos系统的cmd,以管理员身份运行 进入mysql文件夹中的bin目录 安装MySQL的服务mysqld --install 初…

代码随想录刷题第33天

第一题是k次取反后求数组最大和https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/description/,使用了两次贪心策略:第一次是优先将绝对值大的负数进行取反,若负数取完后,取反次数仍有剩余,则将…

幻兽帕鲁游戏联机的时候,显示“网络连接超时”怎么解决?

如果你在游戏联机的时候,显示“网络连接超时”,可以检查下: 1、前提是你已经按照教程部署成功 2、检查防火墙有没有忘记设置,协议是UDP(只有TCP不行,一定要有UDP),端口是否填了8211&…

AI:128-基于机器学习的建筑物能源消耗预测

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

02 c++入门

目录 c关键字命名空间c输入&输出缺省参数函数重载引用内联函数auto关键字(c11)基于范围的for循环(c11)指针空值—nullptr(c11) 0. 本节知识点安排目的 c是在c的基础上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等…

【论文精读】DINO

摘要 基于对ViT在监督学习领域的表现质疑,探究自监督方法下的ViT是否具有更好的特征提取能力,进而发现: 自监督ViT特征包含场景布局、对象边界。这些信息可以在最后一自注意力模块中直接访问。自监督ViT特征结合最近邻分类器(k-NN)分类头中表…

java-8组合式异步编程

11.1 Future 接口 Future接口在Java5中被引人,设计初衷是对将来某个时刻会发生的结果进行建模。它建模了一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。在Future中触发那些潜在耗时的操作把调用…

【VSCode】使用笔记

目录 快捷键系列 相关插件 相关文档链接 快捷键系列 调出终端 ctrl 或者是ctrlJ 结束进程 ctrlc 注释 ctrlkc 取消注释 ctrlku 上下移动代码 alt方向键 多行光标ctrlalt方向键 快速跳过某个单词 ctrl方向键 相关插件 1.每次修改后,自动保存启动项目 相…

【AIGC】Stable Diffusion介绍

Stable Diffusion 是一个基于 OpenAI 的 Diffusion 模型的扩展版本,它采用了稳定扩散(Stable Diffusion)的技术,旨在提高图像生成和处理的质量。下面是 Stable Diffusion 的详细介绍: 基于 Diffusion 的图像生成&…

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱6(附带项目源码)

效果演示 文章目录 效果演示系列目录前言存储加载物品信息源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中,我们将探索如何用unity制作一个3D背包、库存、制作、快…

基于stm32的水产养殖环境监测系统设计

基于STM32的水产养殖环境监测系统设计 一、引言 随着水产养殖业的快速发展,水质管理成为影响养殖效益的关键因素。因此,开发一种基于STM32的水产养殖环境监测系统,用于实时监测水质参数并提供报警机制,对于提高养殖效率、减少损失具有重要意义。 二、系统架构 整个系统…

黄金交易策略(Nerve Nnife.mql4):移动止盈的设计

完整EA:Nerve Knife.ex4黄金交易策略_黄金趋势ea-CSDN博客 相较mt4的止盈止损,在ea上实现移动止盈,可以尽最大可能去获得更高收益。移动止盈的大体逻辑是:到达止盈点就开始追踪止盈,直到在最高盈利点回撤指定点数即平…

内网渗透Searchall敏感凭证信息搜索工具

一、开发背景 在实战中进入内网的时候,大家需要搜集一些敏感信息例如账号,密码甚至浏览器的账号密码。searchall完美解决了这个问题。所以我就结合自身的经验写了一款搜索敏感信息的利用工具。它可以搜索敏感信息,更快为你获取到有价值的信息…

【机器学习】数据清洗之识别重复点

🎈个人主页:甜美的江 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:机器学习 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步…

武器级工具包 Immunity Canvas 7.26安装使用体验

介绍: Immunity Canvas工具包有集成化、自动化、简单化的特点,大幅降低了攻击门槛。该工具是Immunity公司的一款商业级漏洞利用和渗透测试工具,包含了480多个以上的漏洞利用,该工具工具本来并不开源,但是在2021年Immu…