1 解释为什么如下代码会打印 6 个 6
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
首先JS是单线程语言,每段代码的执行就像流水线一样,一步一步的流动下去。而setTimeout延时器的运行机制是会先将回调函数放到等待队列中,等待区域内其他主程序执行完毕后,按时间顺序先进先出执行回调函数。本质上是作用域的问题。
i的作用域是在全局,所以最后会连续输出6个6。
解决思路:人为给i创造作用域,保存记录i的值。
2 写出让上面代码打印 0、1、2、3、4、5 的方法
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
按ES6的语法,let和for循环结合在一起,每次迭代的循环域内都会保存一个i的值,所以此次setTimeout()内匿名函数闭包的调用会获得当前迭代的值。
3 其他方法可以打印出 0、1、2、3、4、5
- 方案一 使用立即执行函数,人为提供一个i的闭包环境
for(var i = 0; i<6; i++){
(function(j) {
setTimeout( function timer() {
console.log( j );
}, 1000 );
})(i);
}
- 将setTimeout的定义和调用分别放到不同部分
function timer(i) {
setTimeout( console.log( i ), 1000 );
}
for (var i=0; i<6;i++) {
timer(i);
}
- setTimeout传入第三个参数
function timer(i){
console.log(i);
}
for (var i = 0; i < 6; i++) {
setTimeout(timer,1000,i);
}