JS 函数的执行时机之setTimeout

本文探讨了JavaScript中setTimeout函数的工作原理,特别是在循环中的使用。举例说明了setTimeout如何等待循环完成后再执行,导致预期结果与实际输出的差异。通过两种方法——使用立即执行函数和try...catch语句——来演示如何正确保存并打印出每个循环迭代的值,以达到预期的输出效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

setTimeout()的意思是设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。

例:

如下代码会打出6个6。

let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

//打印结果6,6,6,6,6,6

其原因是因为:

setTimeout函数会优先执行之前的事件,最后再执行后续的事件。而之前的事件是i循环,显然得等i循环执行完毕再执行打印出i的这个函数,当i等于5时,因为小于6会再执行一次,直到i等于6,一共执行了6次,根据前面所诉会打出6个6,而非6个5


不过,为了让上面的结果变成 012345,可以使用如下的代码。

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

//打印结果0,1,2,3,4,5

在这个情况下,let关键字劫持了for循环的块作用域。通俗解释为JSforlet一起使用的时候会添加东西,每次进入循环的时候会多创建一个i,把i复制一份留在这个空间用于打印,这个所谓的i不是会变的i,是变化之前的拷贝,不跟随变化的i变化,所以一共变化了5次,不会到6,打印出012345

这使得setTimeout毫无意义。


我还提供了2种方法可以打印出012345的方法供大家参考。

1. 使用立即执行函数

for(var i = 0; i < 5; i++) {
    (function(i) {
        setTimeout(function () {
            console.log(i);
        });
    })(i)
}
console.log('a');

//打印结果0,1,2,3,4,5

和上面有点类似,这个是利用闭包的原理,闭包使一个函数可以继续访问它定义时的作用域。而这个新生成的作用域将每一次循环的当前i值单独保存了下来。

2. 使用try...catch语句

for(var i = 0; i < 5; i++) {
    try {
        throw(i)
    } catch(j) {
        setTimeout(function () {
            console.log(j);
        });
    }
}

//打印结果0,1,2,3,4,5

这是因为try...catch语句的catch后面的花括号是一个块作用域,和let的效果一样。所以在try语句块里抛出循环变量i,然后在catch的块作用域里接收到传过来的i,就可以将循环变量保存下来,实现类似闭包let的效果。

来源:https://juejin.cn/post/6844904036177707021
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值