为了账号安全,请及时绑定邮箱和手机立即绑定

JavaScript循环内的闭包为什么返回的是最后一个值

JavaScript循环内的闭包为什么返回的是最后一个值

牛魔王的故事 2019-04-14 10:35:45
错误写法for(vari=0;i
查看完整描述

2 回答

?
缥缈止盈

TA贡献2041条经验 获得超4个赞

//每次循环会调用setTimeout函数,其中指定了一个timeout后执行的函数
//这个函数因为构成闭包的关系,其能够访问外层函数定义的变量,这个变量就是i
//在for循环执行完毕后,i的值为10.此时在事件队列中有10个timeout函数等待执行
//当timeout时间到时,对应的执行函数调用的i都是同一个,也就是10
for(vari=0;i<10;i++){
setTimeout(function(){
console.log(i);
},1000);
}
//在for循环中定义了匿名立即执行函数
//通过将每次循环时产生i传入匿名立即执行函数,立即执行函数就有了一个内部变量e,
//其值是传入的i
//setTimeout函数形成闭包,能访问到其外层函数也就是匿名立即执行函数的变量e
//因为e引用关系的存在,匿名立即执行函数不会被马上销毁掉
//timeout时间一到,指定执行函数调用的e就是每次传入的参数i
for(vari=0;i<10;i++){
(function(e){
setTimeout(function(){
console.log(e);
},1000);
})(i);
}
//整个和上面的类似,只不过把匿名立即执行函数传递给setTimeout的第1个参数中
//匿名立即执行函数,顾名思义就是需要立即执行的呀。
//所以setTimout函数对应的超时执行函数(第1个参数)
//为匿名立即执行函数执行的结果,也就是返回的函数。
//接下来理解就和上面一样啦
for(vari=0;i<10;i++){
setTimeout((function(e){
returnfunction(){
console.log(e);
}
})(i),1000)
}
                            
查看完整回答
反对 回复 2019-04-14
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

因为ES6之前没有块作用域
for(vari=0;i<10;++i){
setTimeout(function(){
console.log(i)
},1000)
}
有块作用域时效果如同
for(vari=0;i<10;++i){
varj=0
j=i
setTimeout(function(){
console.log(j)
},1000)
}
就是块内代码引用的i变量均不是指向同一个变量。而ES6则引入let关键字来标识变量位于块作用域内
for(leti=0;i<10;++i){
setTimeout(function(){console.log(i)},1000)
}
当然在ES3/5下除了通过IIFE构造作用域外,还可以通过with来构造
for(vari=0;i<10;++i)with({i:i}){
setTimeout(function(){console.log(i)},1000)
}
                            
查看完整回答
反对 回复 2019-04-14
  • 2 回答
  • 0 关注
  • 557 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信