for (var i=1;i<=5;i++) {
setTimeout(function(){
console.log(i)
},i*1000)
}
for循环语句是如何运行的呢?为什么会输出5个6呢?
for (var i=1;i<=5;i++) {
setTimeout(function(){
console.log(i)
},i*1000)
}
for循环语句是如何运行的呢?为什么会输出5个6呢?
因为 setTimeout
是异步的啊,当你执行完 for
的时候,设定了 5个setTimeout
,分别延迟 1至5
秒,
执行完 for
后,i
的值为 6,然后你会看到,每隔一秒输出1个6
,一共5个
这是闭包问题,
for (var i=1;i<=5;i++) {
setTimeout(test(i),i*1000)
}
function test(i){
console.log(i)
}
或者
for (var i=1;i<=5;i++) {
setTimeout((function(x){
return function(){
console.log(x)
}
})(i),i*1000)
}
循环里面套函数都会产生这种闭包问题
这个题的重点在于, setTimeout是需要等到你的主程序执行流执行完了后才执行.
一开始, 程序从for开始执行, 遇到setTimeout的时候先不管, 继续往后执行, 一直执行到循环结束.
好了, setTimeout可以执行啦. 连续六个setTimeout打印出i, 而此时的i已经是6啦.
这是由于js没有块级作用域造成的,而不是for循环的问题.
先看这个例子:
var i = 1;
{
var i = 2;
}
console.log(i);
输出的结果是:2.就是说{}
中定义的变量i
会取代{}
外面的变量i
,即没有块级作用域.
每执行一次就相当于执行了一次上面的代码,最后循环中的i是5,又执行了一次i++,所以变成了6;
10 回答11.2k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
闭包,闭包,闭包的问题!
通过上面的代码,可以看出只定义了一个变量
i
,只有在循环里面赋值为1~5
,循环结束后是 6。而
setTimeout
中的代码是在循环之后执行的,所以输出的i
是 6。而不是你所想的。因为 i 只有一个,不可能同时等于
1,2,3,4,5
.可以改成(建议先理解上面一段代码,先不要纠结ES6的):