说说你对闭包的理解?闭包使⽤场景

  • 作用链域
  • 闭包
    • 闭包的特性:
    • 说说你对闭包的理解
    • 使用闭包的注意点
    • 总结
  • 扩展 循环中使用闭包解决 var 定义函数的问题
    • 解决办法有三种

作用链域

JavaScript 的作用域链(Scope Chain)是指在代码中访问变量时的查找路径。

当 JavaScript 引擎在执行代码时,会根据作用域链来确定变量的可访问范围。

作用域链由多个执行上下文(Execution Context)组成,每个执行上下文都有一个关联的变量对象(Variable Object),变量对象保存了当前执行环境中定义的所有变量和函数。

当需要访问一个变量时,引擎会从当前执行上下文的变量对象开始查找,如果找不到,则沿着作用域链继续向上查找,直到全局执行上下文的变量对象。

如果在作用域链的任何级别上找不到该变量,则会抛出 ReferenceError。

作用域链的形成是由变量的作用域规则决定的

在 JavaScript 中,有三种类型的作用域:

  • 全局作用域、
  • 函数作用域
  • 块级作用域。

每个作用域都会创建一个新的执行上下文,并将其添加到当前的作用域链中。

作用域链是 JavaScript 用来管理变量访问权限的一种机制,它决定了变量在代码中的可见性和可访问性。

通过理解作用域链,我们能更好地理解 JavaScript 中的作用域和变量的生命周期。

JavaScript 的作用域链是指在代码中访问变量时的查找路径。我将通过一个例子来说明作用域链的概念。

更多详细内容,请微信搜索“前端爱好者戳我 查看

var globalVariable = 'Global'; // 全局变量function outerFunction() {var outerVariable = 'Outer'; // 外部函数变量function innerFunction() {var innerVariable = 'Inner'; // 内部函数变量console.log(innerVariable); // 在内部函数中访问内部变量console.log(outerVariable); // 在内部函数中访问外部函数变量console.log(globalVariable); // 在内部函数中访问全局变量}innerFunction(); // 调用内部函数
}outerFunction(); // 调用外部函数

在上面的例子中,我们定义了三个不同级别的变量:

  • 全局变量 globalVariable
  • 外部函数变量 outerVariable
  • 内部函数变量 innerVariable

当执行 outerFunction() 后,会创建一个包含 outerVariableinnerFunction 的函数执行上下文(即外部函数的执行上下文)。

然后,在 outerFunction() 中调用 innerFunction() 时,会再次创建一个包含 innerVariable 的函数执行上下文(即内部函数的执行上下文)。

当内部函数访问变量时,JavaScript 引擎会按照作用域链的顺序进行查找。

  • 首先,它会在当前执行上下文的变量对象中查找变量,即在内部函数的执行上下文中查找 innerVariable
    • 如果找到了该变量,则直接使用。
    • 如果没有找到,则会继续向上一级的执行上下文即外部函数的执行上下文中查找,即在外部函数的执行上下文中查找 outerVariable
    • 如果还是找不到,则继续向上一级的执行上下文即全局执行上下文中查找,即在全局执行上下文中查找 globalVariable

在这个例子中,当 innerFunction() 执行时,会按照作用域链的顺序找到并访问到 innerVariableouterVariableglobalVariable

如果在作用域链的任何级别上找不到变量,就会抛出 ReferenceError

这就是作用域链的工作原理,它决定了变量在代码中的可见性和可访问性。

闭包

闭包就是 能够读取其他函数内部变量的函数

闭包是指 有权访问另⼀个函数作用域中变量的函数,创建闭包的最常⻅的方式就是: 在⼀个函数内创建另⼀个函数, 通过另⼀个函数访问这个函数的局部变量,利用闭包可以突破作用链域

闭包的特性:

  • 函数内再嵌套函数
  • 内部函数可以引用外层的参数和变量
  • 参数和变量不会被垃圾回收机制回收

说说你对闭包的理解

  • 使用闭包主要是为了设计私有的方法和变量 。
    • 闭包的优点是可以避免全局变量的污染,
    • 缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

在js中, 函数即闭包, 只有函数才会产生作用域的概念

  • 闭包 的最大用处有两个,

    • ⼀个是可以读取函数内部的变量,
    • 另⼀个就是让这些变量始终保持在内存中
  • 闭包的另⼀个用处, 是封装对象的私有属性和私有方法

    • 好处:能够实现封装和缓存等;
    • 坏处:就是消耗内存 、不正当使用会造成内存溢出的问题

使用闭包的注意点

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

总结

闭包的定义其实很简单: 函数A内部有⼀个函数B , 函数
就是闭包B 可以访问到函数 A 中的变量,那么函数B就是闭包

function A ( ) {let a = 1window .B = function ( ) {console . log( a)}
}
A ( )
B ( ) // 1

闭包存在的意义就是让我们可以间接访问函数内部的变量

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

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

首先因为 setTimeout 是个异步函数,所以会先把循环全部执行完毕, 这时候 i 就是 6 了,所以会输出⼀堆 6

解决办法有三种

第⼀种是使用闭包的方式

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

在上述代码中, 我们首先使用了立即执行函数将 i 传入函数内部, 这个时候值就被固定在了参数 j 上面不会改变, 当下次执行 timer 这个闭包的时候,就可以使用外部函数的变量 j ,从而达到目的

第⼆种就是使用 setTimeout 的第三个参数

这个参数会被当成 timer 函数的参数传入

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

setTimeout 的第三个参数

在 JavaScript 中,setTimeout 函数是用于延迟执行一个函数或一段代码。它的语法如下:

setTimeout(callback, delay, arg1, arg2, ...);

其中:

  • callback 是要执行的函数或代码块。
  • delay 是延迟的时间(以毫秒为单位)。
  • arg1, arg2, … 是可选的参数,在延迟结束后会作为参数传递给回调函数。

现在来看第三个参数,它表示延迟结束后作为参数传递给回调函数的值。这个参数可以是任意类型的数据

让我们通过一个例子来说明第三个参数的使用:

function greet(name) {console.log("Hello, " + name + "!");
}setTimeout(greet, 2000, "John");

在上面的例子中,setTimeout 函数将延迟 2000 毫秒后执行 greet 函数,并且将字符串 "John" 作为参数传递给 greet 函数。当延迟结束后,greet 函数会被调用,并输出 "Hello, John!"

这里的 "John" 就是 setTimeout 的第三个参数,它会在延迟结束后作为参数传递给回调函数 greet

需要注意的是,setTimeout 的第三个参数是可选的,如果不提供,则回调函数不会接收任何参数。如果提供了多个参数,它们会按照顺序传递给回调函数。

第三种就是使用 let 定义 i 了来解决问题了

这个也是最为推荐的方式

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

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

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

相关文章

ubuntu20.04禁用自动更新(禁用更新、禁用自动升级、禁用apt更新、禁用apt升级、禁用软件更新、禁用系统更新)

想要禁用Ubuntu 20.04的所有自动升级&#xff0c;只需要修改两个文件&#xff1a; /etc/apt/apt.conf.d/10periodic&#xff1a; 这个文件控制APT的周期性任务。你需要编辑这个文件并设置所有选项为"0"&#xff0c;这将禁止任何定期的任务。 你可以使用以下命令快速完…

springCloud项目打包如何把jar放到指定目录下

springCloud项目打包如何把jar发放到指定目录下 maven-antrun-plugin springCloud微服务打包jar&#xff0c;模块过多&#xff1b;我的项目模块结构如下&#xff1a; 我把实体类相关的单独抽离一个模块在service-api下服务单独写在service某块下&#xff0c; 每个模块的jar都…

如何使用jQuery获取当前网址路径

如何使用jQuery获取当前网址路径概述在前端开发中&#xff0c;经常需要获取当前网址的路径&#xff0c;通过使用jQuery库&#xff0c;我们可以轻松地实现这个功能。本文将逐步介绍如何使用jQuery获取当前网址路径。流程步骤以下是实现该功能的步骤&#xff1a;步骤 描述…

人工智能导论复习资料

题型 1、简答题&#xff08;5题&#xff09; 2、设计题 3、综合题 4、论述题&#xff08;10分&#xff09; 考点 第一章 1、人工智能的定义、发展&#xff1b; 2、人工智能的学派、认知观及其间的关系&#xff1b; 3、人工智能要素及系统分类&#xff1b; 4、人工智能的研究、…

Python轴承故障诊断 (七)基于EMD-CNN-LSTM的故障分类

目录 前言 1 经验模态分解EMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 制作数据集和对应标签 2.3 故障数据的EMD分解可视化 2.4 故障数据的EMD分解预处理 3 基于EMD-CNN-LSTM的轴承故障诊断分类 3.1 训练数据、测试数据分组&#xff0c;数据分batch 3.…

Fanuc-Focas库函数库中控制机床轴的移动

在Fanuc-Focas库中控制机床轴的移动&#xff0c;通常需要通过调用库函数来实现。具体的函数和参数可能因不同的库版本和机床型号而有所不同&#xff0c;因此请参考相关的Fanuc-Focas文档或手册以获取准确的信息。 一般来说&#xff0c;控制机床轴的移动需要以下几个步骤&#…

canal环境部署

docker 部署canal同步数据 1 环境: 2 Mysql 配置 查看 binlog 是否启用 SHOW VARIABLES LIKE ‘%log_bin%’; 开启 binlog, 修改 my.cnf docker cp mysql:/etc/my.cnf /data/mysql/conf 拷贝文件到临时目录修改后再拷贝回去 # For advice on how to change settings please …

ArchLinux安装使用ifconfig

安装 sudo pacman -S net-tools 使用 ifconfig

【网络安全】网络防护之旅 - 点燃网络安全战场的数字签名烟火

​ &#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《网络安全之道 | 数字征程》⏰墨香寄清辞&#xff1a;千里传信如电光&#xff0c;密码奥妙似仙方。 挑战黑暗剑拔弩张&#xff0c;网络战场誓守长。 ​ 目录 &#x1f608;1. 初识…

Android studio 多渠道打包步骤

在Android Studio中&#xff0c;可以使用Gradle的多渠道打包功能来生成不同渠道的应用包。以下是多渠道打包的步骤&#xff1a; 在项目的build.gradle文件中&#xff0c;添加渠道相关的配置。在android节点下添加productFlavors块&#xff0c;定义不同的渠道&#xff0c;例如&…

渗透实验基础教程(完整版):

#江南的江 #每日鸡汤&#xff1a;影响我们人生的绝不仅仅是环境&#xff0c;其实是心态在控制个人的行动和思想。同时&#xff0c;心态也决定了一个人的视野事业和成就&#xff0c;甚至一生。 #初心和目标&#xff1a;成为网络安全达人。。。 渗透实验基础教程&#xff08;完整…

UniGuiApplication的客户端信息包括以下内容:

UniGuiApplication的客户端信息包括以下内容&#xff1a; UserAgent: 客户端的用户代理信息&#xff0c;用于识别客户端的浏览器类型和版本。Browser: 客户端的浏览器类型&#xff0c;如Chrome、Firefox、Safari等。Platform: 客户端的操作系统平台&#xff0c;如Windows、Mac…

自动驾驶技术:驶向未来的智能之路

导言 自动驾驶技术正引领着汽车产业向着更安全、高效、智能的未来演进。本文将深入研究自动驾驶技术的核心原理、关键技术、应用场景以及对交通、社会的深远影响。 1. 简介 自动驾驶技术是基于先进传感器、计算机视觉、机器学习等技术的创新&#xff0c;旨在实现汽车在不需要人…

关于后端返回给我们的对象或者数组为空时我们把空字符(“”)串变成横杠(“-”)

根据需求&#xff0c;我们分别把他写成两种方法&#xff0c;在我们项目中可以 直接调用该方法&#xff0c;方法如下&#xff1a; 1.把数组中为空的项替换成横杠 //把数组中为空的项替换成横杠 export function filtrateData(data) { data.forEach(obj > { Object.keys(obj)…

鸿蒙(HarmonyOS)应用开发——代理提醒(题目答案)

判断题 1.构造进度条模板通知&#xff0c;name字段当前需要固定配置为downloadTemplate。 正确(True) 2.给通知设置分发时间&#xff0c;需要设置showDeliveryTime为false。 错误(False) 3.OpenHarmony提供后台代理提醒功能&#xff0c;在应用退居后台或退出后&#xff0c…

服务监控-druid监控

一、概述 当前互联网和很多公司&#xff0c;日益都采用阿里数据库连接池druid&#xff0c;druid本身也有监控页面&#xff0c;但是我们自己也需要对监控信息进行采集 &#xff0c;接入自己的监控平台&#xff0c;因此需要能够查询的druid的监控信息 二、方案 方案一&#…

《深入理解计算机系统》学习(3):程序编译和处理器

编译过程 假设一个C程序有两个文件p1.c、p2.c&#xff0c;我们用Unix命令行编译这些代码&#xff1a; linux>gcc -o p p1.c p2.cgcc命令指的就是GCC C编译器&#xff0c;因为这是Linux上默认的编译器&#xff0c;gcc命令调用了一整套程序&#xff0c;将源代码转化为可执行…

Centos安装docker显示 No Package Docker-Ce Available

安装docker 查看当前系统内核 查看方式 uname -r显示如下 [root@test ~]# uname -r 3.10.0-1127.19.1.el7.x86_64重要提示: docker内核版本必须是3.10+以上的版本 1、卸载老版本的 docker 及其相关依赖 yum remove docker docker-common container-selinux docker-selin…

WEB 3D技术 简述React Hook/Class 组件中使用three.js方式

之前 已经讲过了 用vue结合three.js进行开发 那么 自然是少不了react 我们 还是先创建一个文件夹 终端执行 npm init vitelatest输入一下项目名称 然后技术选择 react 也不太清楚大家的基础 那就选择最简单的js 然后 我们就创建完成了 然后 我们用编辑器打开创建好的项目目…

Angular中使用Intersection Observer API实现无限滚动

背景&#xff1a; 实现原理为 在data下面加一个loading元素 如果此元素进入视窗 则调用api获取新的数据加到原来的数据里面&#xff0c;这时loading就会被新数据顶下去&#xff0c;如此循环。 <div id"dataContainer"></div> <div id"loadingCo…