这是一道简单的 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