函数执行时机不同,结果就不同。
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
问:为什么最后会输出6个6?
答:setTimeout ()函数可以理解为尽快执行,也就是执行完当前手头的任务再执行setTimeout()函数。当for循环遇上setTimeout()函数时,先执行完for循环,再执行setTimeout()。上述代码,for循环结束时i=6,且共执行了6次,所以setTimeout()函数在for循环结束后,也会执行6次,所以最后的输出结果是6个6。
写出让上面代码打印 0、1、2、3、4、5 的方法
方法一:临时变量
let i;
for(let i = 0; i< 6; i++){
let j=i
setTimeout(()=>{
console.log(j)
},0)
}
词法作用域根据源代码中声明变量的位置来确定该变量在何处可用
方法二:let 放在 for 里面
for(let i = 0; i < 6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
因为let将i绑定到for循环中,将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的箭头函数属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以箭头函数就能使用i这个变量了;利用了箭头(匿名)函数的参数作用域和for循环的参数作用域不一样。
方法三:setTimeout()的第三个参数
setTimeout()的第三个参数会被传到setTimeout()的回调函数中
let i = 0
for (i = 0; i < 6; i++) {
setTimeout((value)=> {
console.log(value );
}, 0, i );
}
方法四:立即执行函数
let i = 0
for ( i=0; i < 6; i++) {
(function(value) {
setTimeout(()=> {
console.log( value );
}, 0 );
})(i);
}
将i的变量驻留在内存中,当输出value时,引用的是外部函数的变量值i,i的值是根据循环来的,执行setTimeout()时已经确定了里面的的输出了。