前端面试题中的 for循环 + setTimeout

js 定时器笔试题

  1. 分析以下代码实际运行的结果:
for (var i = 0; i < 5; i++) {
 setTimeout(function() {
  console.log(new Date, i);
 }, 1000);
}
console.log(new Date, i);

JS 中同步和异步代码的区别、变量作用域、闭包等概念有正确的理解,就应该知道上面代码的输出结果:

Tue Mar 06 2018 10: 10: 26 GMT + 0800(中国标准时间) 5
Tue Mar 06 2018 10: 10: 27 GMT + 0800(中国标准时间) 5
Tue Mar 06 2018 10: 10: 27 GMT + 0800(中国标准时间) 5
Tue Mar 06 2018 10: 10: 27 GMT + 0800(中国标准时间) 5
Tue Mar 06 2018 10: 10: 27 GMT + 0800(中国标准时间) 5
Tue Mar 06 2018 10: 10: 27 GMT + 0800(中国标准时间) 5
  1. 如果想间隔1s输出一个数字,修改如下
for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date(), i)
    }, i * 1000) // 这里的将上面的1000改为i*1000
}
console.log(new Date(), i);

输出的结果如下

Tue Mar 06 2018 12:20:28 GMT+0800 (中国标准时间) 5
Tue Mar 06 2018 12:20:28 GMT+0800 (中国标准时间) 5
Tue Mar 06 2018 12:20:29 GMT+0800 (中国标准时间) 5
Tue Mar 06 2018 12:20:30 GMT+0800 (中国标准时间) 5
Tue Mar 06 2018 12:20:31 GMT+0800 (中国标准时间) 5
Tue Mar 06 2018 12:20:32 GMT+0800 (中国标准时间) 5
  1. 如果想输出不同的数字,则需要使用闭包,这里使用自执行函数,也可以使用 let 代替 var 声明 i
for (var i = 0; i < 5; i++) {
    (j => {
        setTimeout(function() {
            console.log(new Date, j)
        }, j * 1000)
    })(i) 
}
console.log(new Date,i)

输入结果如下

Tue Mar 06 2018 12:54:46 GMT+0800 (中国标准时间) 5
Tue Mar 06 2018 12:54:46 GMT+0800 (中国标准时间) 0
Tue Mar 06 2018 12:54:47 GMT+0800 (中国标准时间) 1
Tue Mar 06 2018 12:54:48 GMT+0800 (中国标准时间) 2
Tue Mar 06 2018 12:54:49 GMT+0800 (中国标准时间) 3
Tue Mar 06 2018 12:54:50 GMT+0800 (中国标准时间) 4
  1. 使用Generator函数

Generator 函数是 ES6 提供的一种异步编程解决方案.

for...of循环可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法。

function* foo() {
    for (let i = 0; i < 5; i++) {
        yield i;
    }
    return 6;
}
for (let j of foo()) {
    setTimeout(() => {
        console.log(new Date, j)
    }, j * 1000)
}

输出如下

Tue Mar 06 2018 13:41:39 GMT+0800 (中国标准时间) 0
Tue Mar 06 2018 13:41:40 GMT+0800 (中国标准时间) 1
Tue Mar 06 2018 13:41:41 GMT+0800 (中国标准时间) 2
Tue Mar 06 2018 13:41:42 GMT+0800 (中国标准时间) 3
Tue Mar 06 2018 13:41:43 GMT+0800 (中国标准时间) 4
  1. 使用ES7中的async函数

async 函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

// 模拟其他语言中的 sleep,实际上可以是任何异步操作
const sleep = (timeountMS) => new Promise((resolve) => {
    setTimeout(resolve, timeountMS);
});

(async() => { // 声明即执行的 async 函数表达式
    for (var i = 0; i < 5; i++) {
        await sleep(1000);
        console.log(new Date, i);
    }
    await sleep(1000);
    console.log(new Date, i);
})();

输出如下

Tue Mar 06 2018 13:52:22 GMT+0800 (中国标准时间) 0
Tue Mar 06 2018 13:52:23 GMT+0800 (中国标准时间) 1
Tue Mar 06 2018 13:52:24 GMT+0800 (中国标准时间) 2
Tue Mar 06 2018 13:52:25 GMT+0800 (中国标准时间) 3
Tue Mar 06 2018 13:52:26 GMT+0800 (中国标准时间) 4
Tue Mar 06 2018 13:52:27 GMT+0800 (中国标准时间) 5
  1. 使用 Promise
function delay(time) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve, time);
    })
}
for (let i = 0; i < 5; i++) {
    delay(i * 1000).then(() => console.log(new Date, i))
}

输出如下

Fri Mar 16 2018 09:57:04 GMT+0800 (中国标准时间) 0
Fri Mar 16 2018 09:57:05 GMT+0800 (中国标准时间) 1
Fri Mar 16 2018 09:57:06 GMT+0800 (中国标准时间) 2
Fri Mar 16 2018 09:57:07 GMT+0800 (中国标准时间) 3
Fri Mar 16 2018 09:57:08 GMT+0800 (中国标准时间) 4
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值