ITPub博客

首页 > IT职业 > IT生活 > 循环和闭包

循环和闭包

IT生活 作者:tonnyluo 时间:2021-09-09 09:14:52 0 删除 编辑

想要说明闭包,for循环是最常见的例子:

for(var i=1;i

以我们所想,我们可能认为他会输出1~5,每秒一次,每次一个。
但实际上,这段代码在运行时会以每秒一次的频率输出五次6。

这是为什么?

原因是延迟函数会在循环结束时才执行,事实上,当定时器运行时即使每个迭代中执行的是setTimeout(...,0),所有的回调函数依然是在循环结束后才会执行,因此会每次输出一个6出来。

根据作用域的原理,实际情况:尽管循环中的五个函数是在各个迭代中分别定义的,但是他们都被封闭在一个共享的全局作用域中,因此实际上只有一个i。
所以所有函数共享一个i的引用时,循环结构让我们误认为背后还有更复杂的机制在器作用,但实际上啥都木有,如果将延迟函数的回调重复定义五次,完全不使用循环,那他同这段代码是完全等价的。

解决方法如下:
我们先试一下:

    for(var i=1;i

看似可以,但实际也没用,虽然这样写我们有更多词法作用域了,的确每个延迟函数都会将IIFE在每次迭代中创建的作用域封闭起来。
如果作用域是空的,那么仅仅将他们进行封闭是不够的。仔细看一下,我们的IIFE只是一个什么都没有的空作用域,所以需要包含一点实际内容为我们所用。

他需要自己的变量,用来在每个迭代中存储i的值:

    for(var i=0;i

ok,他运行如我们所愿了!

可以进行改进:

    for(var i=1;i

在迭代内使用IIFE会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部,每个迭代中都会包含一个具有正确值的变量供我们访问。

使用let解决

for循环的let声明还会有一个特殊行为,这个行为之处变量在循环过程中不知被声明一次,每次迭代都会声明,随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。

                 

    for(var i=1;i

作者:咸鱼的今生前世                            
来源:https://segmentfault.com/a/1190000014834135?utm_source=channel-hottest          



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2298/viewspace-2808968/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-04-16

  • 博文量
    76
  • 访问量
    678