新手个人理解 如有误解 敬请各位前辈评论指出 谢谢
例1: for循环setTimeout定时器:
for(var i = 1 ; i <= 5; i++){
(function(){
setTimeout(function timer(){
console.log(i);
},1000*i);
})();
}
上述代码预期分别输出 1 2 3 4 5 但是实际输出 6 6 6 6 6
原因:由于for循环与setTimeout函数是同步执行函数,而console.out是异步执行函数。异步执行函数需等待同步执行函数执行完毕才开始执行。所以当for循环与定时器全部加载执行完毕放进执行栈之后(即i=6时)console.log开始初始化。所以就出现了五次定时器循环的输出6.
例2: 函数实参传递:
for(var i = 1 ; i <= 5; i++){
(function(j){
setTimeout(function timer(){
console.log(j);
},1000*j);
})(i);
}
而这种写法就可以正确的输出预期结果。因为函数内不是直接传递for循环的值,将for循环与函数分离开来,通过参数的传递连接。这样console.log就不用等待for循环全部执行完毕。
例3: let循环的setTimeout定时器:
for(let i = 1 ; i <= 5; i++){
(function(){
setTimeout(function timer(){
console.log(i);
},1000*i);
})();
}
let定义的循环体也是可以正常输出预期。因为let的作用域实在代码块中,声明只能在自身的块里声明,不是像var那样作用于函数,所以就等于每一次循环都重新定义一次let i,这样循环就只能一次次给函数传值。在这里let本质上就是形成了一个闭包,就像例4。
例4:
var loop = function(_i){
setTimeout(function timer(){
console.log(_i);
},1000*_i);
}
for(var i = 1 ; i <= 5; i++){loop(i);
}
闭包概念:当内部函数以某一种方式被任何一个外部函数作用域访问时,一个闭包就产生了!