执行以下程序,下列选项中,输出结果正确的是()
for(var i = 0;i<2;i++){
setTimeout(function(){console.log(i)},0) ....①
}
for(var i = 0;i<2;i++){
(function(i){
setTimeout(function(){console.log(i);},0) ...②
}(i))
}
A
①式输出结果为0 1
B
①式输出结果为1 1
C
②式输出结果为0 1
D
②式输出结果为1 1
正确答案:C
对于①式,虽然定时器的延迟执行时间为0秒,但是不影响定时器为异步任务,即定时器的执行在循环结束后,
当i = 2时,循环结束,此时再执行定时器的异步任务,输出结果为2 2;
对于②式,立即执行函数会形成独立的作用域,用来临时封装变量i,i从0到1,对应两个立即执行函数,同时,立即执行函数将i值传递给定时器。
立即执行函数IIFE 闭包 作用域链
A.setTimeout是异步的,定时函数被加入执行队列,等(for循环)主程序运行完毕时,此时再调用定时函数,i的值已经变为2,两次的定时函数都会共用i=2这个值,因此打印2个2
B. js的作用域是链式的,当for循环函数内部的子块有引用的时候是不会销毁的。这里运用了闭包,外层 function(i)保持着对i的引用,因此每次 i的值得以保留,每次调用定时函数内层function都有自己的私有变量值。 因此打印 0 1
②式中如果把function的参数i去掉,没有对i的引用,结果就和①式一样了
for(var i = 0;i<2;i++){
(function(){ //去掉参数i
setTimeout(function(){console.log(i);},0)
}())
}
// 2 2