JS中for循环和定时器

js中for循环和定时器的问题,有四个解决方法
这里面涉及到了同步与异步的问题
也可以理解为:
解决方法1:闭包
解决方法2:拆分结构
解决方法3:let
let和var区别
解决方法4:第三个参数
for (var i = 0; i < 6; i++) {
            setTimeout(() => {
                console.log(i);
            }, 1000);
        }
1
2
3
4
5
如上代码,我们编写代码的思路是想要使 0 1 2 3 4 5间隔1秒陆续出现
但是真正的结果是连续输出6个6

这里面涉及到了同步与异步的问题
setTimeout是异步执行的,每一次执行一次for循环时,setTimeout都会执行一次,但是里面的函数却不会执行,而是被放在了任务对列里面,也就是说只有主线上的全部执行完才会执行任务队列里的任务 == for循环全部执行完毕后(此时 i=5),才开始执行fun函数,因此虽然定时器跑了6秒,但控制台上是6个6

也可以理解为:
(for循环非常的快,从开始到结束只需要几微妙或几毫秒,当定时器跑完一秒之后for循环早就全部执行完成)

解决方法1:闭包
 for (var i = 0; i < 6; i++) {
            (function(j) {
                setTimeout(() => {
                    console.log(j);
                }, j * 1000);
            }(i));
            // 代码格式
           // (function(a) {})(b)
        }
1
2
3
4
5
6
7
8
9
我们可以发现跟预期结果一致,依次输出1到5,因是因为实际参数跟定时器内部的i有强依赖。

通过闭包,将i的变量驻留在内存中,当输出j时,引用的是外部函数的变量值i,i的值是根据循环来的,执行setTimeout时已经确定了里面的的输出了。

解决方法2:拆分结构
  function timeout(i) {
            setTimeout(console.log(i), i * 1000);
        }
        for (var i = 0; i < 6; i++) {
            timeout(i);
        }
1
2
3
4
5
6
这个是在网上看到的,确实可以输出1到5,但似乎没有做到一秒一个,仅供参考

解决方法3:let
 for (let i = 0; i < 6; i++) {
            setTimeout(function() {
                console.log(i);
            }, i * 1000)
        }
1
2
3
4
5
这个强烈推荐,简单好记还有用!!!!!

只把var改为let,可却可以输出1到5,而且是一秒一个数,并不是按设定是时间执行的
因为for循环头部的let不仅将i绑定到for循环中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以function就能使用i这个变量了;这个匿名函数的参数作用域和for参数的作用域不一样,是利用了这一点来完成的。这个匿名函数的作用域有点类似类的属性,是可以被内层方法使用的。

解决方法4:第三个参数
 for (let i = 0; i < 6; i++) {
            setTimeout(function() {
                console.log(i);
            }, i * 1000, i)
        }
1
2
3
4
5
由于每次都是从for里面取到的值,所以会依次输出1到5,试了一下,这种方法最方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值