有人可以解释下面代码和javascript的行为
for(var i = 0; i < 5; i++)
{
setTimeout(function(){
document.write('Iteration ' + i + ' <br>');
},1000);
}
document.write('DONE!');
为什么打印&#39; DONE!&#39;第一? 不应该打印循环的所有值,然后打印“完成”!&#39;?
答案 0 :(得分:5)
为什么打印'完成!'第一?它不应该打印循环的所有值,然后打印'完成!'?
不,你明确告诉它不要;相反,你刚刚创建了五个函数并调用了setTimeout
五次,以便将它们提供给浏览器以便稍后调用。
此代码:
setTimeout(function(){
document.write('Iteration ' + i + ' <br>');
},1000);
调用函数setTimeout
,传入您看到的函数。那时候该功能不。它刚刚创建。 setTimeout
将称之为以后,就像它的工作一样。 (当它发生时,它会吹走文档,因为在页面的主要解析完成之后调用document.write
隐式地完成了document.open
,这会消除之前的文档。)
所以这就是代码所发生的事情:
i
。0
。setTimeout
时传入函数对象的引用以及值1000
。i
会增加。1
的值2
,3
,4
和i
。document.write
调用'DONE!'
document.write
,它隐含地执行document.open
,它会吹走现有文档并将其替换为Iteration 5 <br>
(是的,真的是5)。我们看到Iteration 5
五次而不是Iteration 0
,然后是Iteration 1
等等,是因为这些函数对变量有持久的引用i
,而不是它们在创建时的值,所以它们都会在以后读取它的值,就像它们运行时一样。
答案 1 :(得分:0)
正常的Javascript是Synchronous
逐行Exectue,但是随着代码更改,您可以在某个时候执行异步操作,但它实际上不会在单独的线程上执行。
好的,如果您想在Document.write完成后打印Done
该怎么办
length = 0;
for(var i = 0; i < 5; i++)
{
setTimeout(function(index){
console.log('Iteration ' + index + ' <br>');
length++;
callback();
}(i),1000);
}
function callback(){
if(length == 5)
console.log('DONE!');
}
我们在这里做的是增加计数器并尝试在每次递增后调用回调,当计数器达到5表示调用所有5个函数然后我们能够打印Done
。 / p>
作为一个侧面和重要的注释,你试图打印0,1,2,3,4但实际上当你运行你的代码时它会给你5,5,5,5,5,因为你写{打印时{1}}和i
达到5,这就是为什么它会离开for循环,但是你注意到我添加的代码,我将i
作为参数传递给函数,以便它将为我们保存值,当执行功能时,它将写入0,1,2,3,4