for 循环里面使用 setTimeout
这是一道简单的 JS 面试题,在这里记录一下它的6种方法,共勉。
for(var i = 0; i < 5; i++) { setTimeout(() => { console.log(i) }, 1000) } console.log(i)复制代码
输出结果:5 -> 5,5,5,5,5 (箭头表示1s,逗号表示几乎同时输出)
1. 借助 let 的暂时性死区
for(let i = 0; i < 5; i++) { setTimeout(() => { console.log(i) }, 1000) } console.log(i)复制代码
输出结果:5 -> 0,1,2,3,4
2. 借助 setTimeout 的第三个参数
for(var i = 0; i < 5; i++) { setTimeout((j) => { console.log(j) }, 1000, i) } console.log(i)复制代码
输出结果:5 -> 0,1,2,3,4
3. 借助立即执行函数
for(var i = 0; i < 5; i++) { ((j) => { setTimeout(() => { console.log(j) }, 1000) })(i) } console.log(i)复制代码
输出结果:5 -> 0,1,2,3,4
4. 借助形参的特性
var sleepConsole = (i) => { setTimeout(() => { console.log(i) }, 1000) } for(var i = 0; i < 5; i++) { sleepConsole(i) // i会被复制后传递 } console.log(i)复制代码
输出结果:5 -> 0,1,2,3,4
5. 借助 Promise
// 1.建立数组存储 Promise const task = [] // 2.抽取方法生成异步操作 const output = (i) => new Promise(resolve => { setTimeout(() => { console.log(i) resolve() }, 1000 * i) }) // 3.循环执行异步操作 for(var i = 0; i < 5; i++) { task.push(output(i)) } // 4.异步操作执行完成后输出最后的i Promise.all(task).then(() => { setTimeout(() => { console.log(i) }, 1000) })复制代码
输出结果:0 -> 1 -> 2 -> 3 -> 4 -> 5
6. 借助 async/await
// 生成休眠函数 const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) (async () => { for(var i = 0; i < 5; i++) { if (i > 0) { await sleep(1000) } console.log(i) } await sleep(1000) console.log(i) })()复制代码
输出结果:0 -> 1 -> 2 -> 3 -> 4 -> 5
作者:别动我的糖醋排骨
链接:https://juejin.cn/post/7019233455645032455