for循环的定时器问答

这是一道很经典的面试题,其中确是会让写了很多年js代码的人都会感到困扰。

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

执行结果:在1s后同时输出5个5

那么其中是不是有很多想不明白的问题呢

思考1:为什么 console.log的结果是5 ,而不是4?

答案1:如果你对这个问题感到疑惑的话,那么你就要弄明白for循环的执行顺序

for (var i = 0; i < 5; i++) {}
    ①首先执行计时器变量var i = 0,且在这个循环中只执行一次
    ②循环开始前,用i判断是否i<5成立,如果为真,进入循环体,如果为假,跳出循环体
    ③执行i++(无论是否条件判断成立,都会执行这一步)
    ④更新计时器,重复②③
  


具体步骤

for (var i = 0; i < 5; i++) {}
    1.var i=0
    2.0<5 成立 执行循环体
    3.执行i++,更新i,i=1
    4.1<5 成立 执行循环体
    5.执行i++,更新i,i=2
    6.2<5 成立 执行循环体
    7.执行i++,更新i,i=3
    8.3<5 成立 执行循环体
    9.执行i++,更新i,i=4
    10.4<5 成立 执行循环体
    11.执行i++,更新i,i=5
    12.5<5 不成立 跳出循环体,循环结束

  所以,我们最后得到的i其实是5

思考2:为什么定时器是同时在1s后输出,而不是间隔1s输出?



     setTimeout(function() {
         console.log(i);
     }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

注意,后面的5个定时任务都是在1s后同时执行,所以不存在间隔1s的情况

思考3:为什么console.log的结果不是0,1,2,3,4 

这个问题你需要知道以下两点
1.他的执行步骤是先触发同步任务,然后在执行异步任务
2.es3的语法var并没有块结构的说法
    
for循环就是同步任务,定时器就是异步任务
    
所以我们可以将这个面试题目进行解析:
    
for (var i = 0; i < 5; i++) {}

    i = 5

在进入循环前,i早已经赋值成为5,

   setTimeout(function() {
         console.log(i);
     }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

    setTimeout(function() {
        console.log(i);
    }, 1000);

如果想要达到输出0,1,2,3,4的效果,我们可以将var换成let

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

理解一下来自《JavaScript高级程序设计(第4版)》的这句话,JS引擎会为for循环中的let声明分别创建独立的变量实例,即

使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。并且是在块中声明的,他的运行过程就可以是


{
    let i=0;
    setTimeout(function() {
         console.log(i);
     }, 1000);
}


   {
    let i=1;
    setTimeout(function() {
         console.log(i);
     }, 1000);
}
{
    let i=2;
    setTimeout(function() {
         console.log(i);
     }, 1000);
}
{
    let i=3;
    setTimeout(function() {
         console.log(i);
     }, 1000);
}
{
    let i=4;
    setTimeout(function() {
         console.log(i);
     }, 1000);
}
即在let中,每个i都是指向当时创建的新变量,0,1,2,3,4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值