循环中解决var定义函数的问题

9ccad8ada0cb44a7b67f7e2254ae3058.png

  在上述代码中,setTimeout 是个异步函数,所以会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆 6。

解决办法有三种:

1、使用闭包的方式+立即执行函数

68678f3f550944f79b8ce50834c7be3e.png

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

2、使用 setTimeout 的第三个参数

f6c0f38c7b644e5aa661e69689469827.png

这个参数会被当成 timer 函数的参数传入,先行执行。

3、使用 let 定义 i

74ba47c00cc844949830937b0f034b54.png

其原理是:

在var里面,setTimeout是异步执⾏,i * 1000ms 后往任务队列⾥⾯添加⼀个任务,只有主线线上的全部执⾏完,才会执⾏任务队列⾥的任务,当主线执⾏完成后,i 是 6,所以此时再去执⾏任务队列⾥的任务时,i 全部是6了。

 每⼀次for循环的时候,settimeout都执⾏⼀次,但是⾥⾯的函数没有被执⾏,⽽是被放到了任务队列⾥⾯,等待执⾏,for循环了6次,就放了6次,当主线程执行完成后,才进入任务队列里面执行。

而在let里面,因为for循环头部的 let 不仅将 i 绑定到 for 循环中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以function就能使用 i 这个变量了。

注意:

  由于 var 命令的变量提升机制,var 命令实际只会执行一次,而 let 命令不存在变量提升,所以每次循环都会执行一次,声明一个新变量(但初始化的值不同),for 的每次循环都是不同的块级作用域,let 声明的变量也是块级作用域,所以也不存在重复声明的问题,let 声明变量的 for 循环里,每个匿名函数实际上引用的都是一个新的变量。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值