首页 > 其他分享 >实现异步循环--闭包

实现异步循环--闭包

时间:2023-12-27 13:46:49浏览次数:24  
标签:闭包 异步 函数 -- 作用域 let var

让我们试着写一个异步方法,每秒打印一次循环的索引值。

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

如上程序的输出为:

> 5
> 5
> 5
> 5
> 5

这明显是有问题的。

原因

每次时间结束(timeout)都指向原始的i,而并非它的拷贝。所以,for循环使i增长到5,之后timeout运行并调用了当前i的值(也就是5)。

好吧,这个问题看起来很简单。最直接的解决方法是将循环的索引缓存在一个临时变量里。

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

但是再次运行,如上的程序输出为:

> 4
> 4
> 4
> 4
> 4

这仍然有问题,这是因为并不存在块作用域,而且变量的声明被提升到了作用域顶端。实际上,如上代码和下面是一样的:

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

解决方法

有几个不同的方式可以拷贝i。最普通且常用方法是通过声明函数来建立一个闭包,并将i传给此函数。我们这里使用了自调用函数。

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

在JavaScript里,参数是按值传递给函数的。像NumberDateString这些原始类型为基本复制。当你们在一个函数内改变它的值,并不影响外面的作用域。但Object类型不一样:如果你在函数内部修改了它的参数,将会影响到所有包含该Object的作用域内它的参数。

另一种方法是使用let。在ES6中的let关键字是可以实现的,它和var不一样,因为它支持块作用域的。

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

标签:闭包,异步,函数,--,作用域,let,var
From: https://www.cnblogs.com/fdxjava/p/17930369.html

相关文章

  • Java 简单工厂模式
    需求:Pizza有以下几个方法prepare()准备食材bake()烘焙cut()切割box()装盒现在有两种披萨,第一种是ApplePizza,第二种是CheesePizza。PizzaStore有点单系统Order(pizzaType)根据pizzatype去制作对应的Pizza。Pizza的抽象类publicabstractclassPizza{Strin......
  • 为什么主流公司都使用jenkins
    手动打包常规步骤:1.提交代码2.问一下同组小伙伴有没有要提交的代码3.拉取代码并打包(war包,或者jar包)4.上传到Linux服务器5.查看当前程序是否在运行6.关闭当前程序7.启动新的jar包8.观察日志看是否启动成功9.如果有同事说,自己还有代码没有提交.......
  • 敏捷开发模型
    敏捷开发的最大特点是高度迭代,有周期性,并且能够及时、持续地响应客户的频繁反馈。敏捷测试即是不断修正质量指标,正确建立测试策略,确认客户的有效需求能得以圆满实现和确保整个生产的过程安全的、及时的发布最终产品。敏捷测试是遵循敏捷宣言的一种测试实践1、强调从客户的角度,即......
  • break 或 continue 循环函数,使用some同forEarch一样,但是直到找到就不继续往下循环,节省
    停止循环是循环中一个常见的需求。使用for循环我们可以用break提前结束循环。consta=[0,1,2,3,4];for(vari=0;i<a.length;i++){if(a[i]===2){break;//stoptheloop}console.log(a[i]);}//>0,1另一个常见的需求使我们需要直接取......
  • 超轻量级MP4封装方法介绍
    liwen012023.12.17前言MP4是目前非常常用的一种视频封装格式,关于MP4的介绍资料也非常多。我们常用的封装库或工具有:ffmpeg,libmp4v2,GPAC,MP4.js,它们的优点是功能基本上都是比较全面,缺点就是它们占用的资源相对来说也是非常多的。在嵌入式系统中,不管是RAM还是FLASH空间,一般都是非......
  • Jenkins自动化部署实现原理
     1.jdk环境,Jenkins是java语言开发的,因需要jdk环境。2.git/svn客户端,因一般代码是放在git/svn服务器上的,我们需要拉取代码。3.maven客户端,因一般java程序是由maven工程,需要maven打包,当然也有其他打包方式,如:gradle。4.Jenkins可以不用安装tomcat,只要有Java环境就可以,它可以自己启......
  • 数据可视化结合2D地图能够给我们带来什么样的变化?
    在信息时代,数据可视化与2D地图的结合为我们的生活和工作带来了深刻的变革。这一强大的组合不仅为我们提供了全新的视角,更为各行各业的发展和决策提供了更为精准的指导。下面我就以可视化从业者的视角,来简单聊聊数据可视化和2D地图的结合。首先,结合2D地图的数据可视化为城市规划和......
  • 清空数组的两种方法
    如果你定义了一个数组,然后你想清空它。通常,你会这样做://定义一个数组varlist=[1,2,3,4];functionempty(){//清空数组list=[];}empty();但是,这有一个效率更高的方法来清空数组。你可以这样写:varlist=[1,2,3,4];functionempty(){......
  • Jenkins基本配置
     1.ConfigureSystem(系统设置)在系统设置这里,只需要设置最后面的一项,配置远程服务器地址,即代码最终运行的服务器地址信息,当然这里是可以配置多台远程Linux服务器的,配置完成后点击保存即可,为后面配置自动化部署做准备,配置如下图 2.Configure GlobalSecurity(全局安全配......
  • 内网安全管理系统的作用和价值有哪些?
    什么是内网安全管理系统内网安全管理系统是一种用于保护企业或组织内部网络中的各种资源和数据的安全的系统,它涵盖了终端管理、网络管理、内容管理、资产管理等多个方面,实现了对内网的全面监控和控制。内网安全管理系统的主要功能有:终端管理:对内网中的各种终端设备(如PC、手机......