js的作用域是链式的,当for循环函数内部的子块有引用的时候是不会销毁的。这里运用了闭包,外层 function(i)保持着对i的引用,因此每次 i的值得以保留,每次调用定时函数内层function都有自己的私有变量值。

发布时间 2023-11-16 14:01:53作者: 龙陌

执行以下程序,下列选项中,输出结果正确的是()

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