在说这个问题之前,我们先来看一下下面这段代码:
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
这段代码的运行结果会让控制台打印出6个6,这是为什么呢?
setTimeout语句把console.log(i)
放入等待区,等待当前语句全部执行完后,调用等待区中的6个console.log(i)
。而第一句代码let i = 0
会在最外部的环境声明一个变量i
,而for循环中的每一次循环时用到的变量i,都是同一个变量。在for循环全部执行完毕后,内存中变量i
的值变为6,这时等待区的console.log(i)
语句中的i,全部都是内存中已经变为6的i变量,因此会打印出6个6。
打印出0,1,2,3,4,5的方法
- ES6:
for(let i = 0; i < 6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
仅仅是把i的定义放入循环条件中初始化,就能简单的实现按顺序打印i的值。这是因为在循环条件中初始化的i,实际上在每一次循环时,都将该值复制一份放在当前循环体中使用。
- ES6以前的办法:
for(var i = 0; i < 6; i++){
(function(i){
setTimeout(function(){
console.log(i);
},0);
})(i);
}
在ES6以前要想实现类似的效果,就必须使用闭包来实现,循环体中的匿名函数可以使用外层for循环作用域的变量i,原理是把每一次循环的var i
的值复制一份当做参数传递给匿名函数,用这种方法实现预期效果。