javascript(同步或异步)的执行流程
flow of execution of javascript(synchronous or asynchronous)
有人可以向我解释以下代码的行为吗 javascript
for(var i = 0; i < 5; i++)
{
setTimeout(function(){
document.write('Iteration ' + i + ' <br>');
},1000);
}
document.write('DONE!');
为什么先打印'DONE!'?
它不应该打印循环的所有值然后打印 'DONE!'?
why does it print 'DONE!' first? Shouldn't it print all values of the loop and then print 'DONE!'?
不,你已经明确告诉它不要这样做;相反,您刚刚创建了五个函数并调用了 setTimeout
五次以将它们提供给浏览器稍后调用。
此代码:
setTimeout(function(){
document.write('Iteration ' + i + ' <br>');
},1000);
调用函数setTimeout
,传入你看到的函数。那个函数是 not 当时调用的。它刚刚创建。 setTimeout
以后 会称它为它的工作。 (当它这样做时,它会清除文档,因为在页面的主要解析完成后调用 document.write
会隐式地执行 document.open
,这会清除之前的文档。)
下面是这段代码的结果:
- 变量
i
已创建。
- 设为
0
。
- 函数已创建。
调用 setTimeout
时传入该函数对象的引用以及值 1000
.
i
递增。
- 对
i
的值 1
、2
、3
和 4
重复步骤 2 到 5。
document.write
以值 'DONE!'
调用
- 大约一秒钟后,浏览器调用循环中创建的第一个函数。
- 该函数调用
document.write
,它隐含地执行 document.open
,它会清除现有文档并将其替换为 Iteration 5 <br>
(是的,真的是 5)。
- 循环中创建的第二个函数是运行,再次输出消息。
- 调用其余三个函数,将消息再添加三次。
我们看到 Iteration 5
五次而不是 Iteration 0
,然后是 Iteration 1
等的原因是这些函数具有对 变量的持久引用 i
,不是创建的时候的值,所以都是后来读取的值,到运行.
的时候
Javascript 在正常情况下是 Synchronous
逐行执行,但是随着代码更改,您有时可以充当异步,但它实际上不会在单独的线程上执行。
好的,如果你想在 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
.
附带重要说明,您尝试打印 0、1、2、3、4,但实际上当您 运行 您的代码时,它会给您 5、5、5、,5 , 5 因为你在打印达到 5 时写了 i
和 i
这就是它退出 for 循环的原因,但是你注意到我添加的代码,我通过 i
作为函数的参数,这样它会为我们保存值,当执行函数时它会写入 0, 1, 2, 3, 4
有人可以向我解释以下代码的行为吗 javascript
for(var i = 0; i < 5; i++)
{
setTimeout(function(){
document.write('Iteration ' + i + ' <br>');
},1000);
}
document.write('DONE!');
为什么先打印'DONE!'? 它不应该打印循环的所有值然后打印 'DONE!'?
why does it print 'DONE!' first? Shouldn't it print all values of the loop and then print 'DONE!'?
不,你已经明确告诉它不要这样做;相反,您刚刚创建了五个函数并调用了 setTimeout
五次以将它们提供给浏览器稍后调用。
此代码:
setTimeout(function(){
document.write('Iteration ' + i + ' <br>');
},1000);
调用函数setTimeout
,传入你看到的函数。那个函数是 not 当时调用的。它刚刚创建。 setTimeout
以后 会称它为它的工作。 (当它这样做时,它会清除文档,因为在页面的主要解析完成后调用 document.write
会隐式地执行 document.open
,这会清除之前的文档。)
下面是这段代码的结果:
- 变量
i
已创建。 - 设为
0
。 - 函数已创建。 调用
setTimeout
时传入该函数对象的引用以及值1000
.i
递增。- 对
i
的值1
、2
、3
和4
重复步骤 2 到 5。 document.write
以值'DONE!'
调用
- 大约一秒钟后,浏览器调用循环中创建的第一个函数。
- 该函数调用
document.write
,它隐含地执行document.open
,它会清除现有文档并将其替换为Iteration 5 <br>
(是的,真的是 5)。 - 循环中创建的第二个函数是运行,再次输出消息。
- 调用其余三个函数,将消息再添加三次。
我们看到 Iteration 5
五次而不是 Iteration 0
,然后是 Iteration 1
等的原因是这些函数具有对 变量的持久引用 i
,不是创建的时候的值,所以都是后来读取的值,到运行.
Javascript 在正常情况下是 Synchronous
逐行执行,但是随着代码更改,您有时可以充当异步,但它实际上不会在单独的线程上执行。
好的,如果你想在 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
.
附带重要说明,您尝试打印 0、1、2、3、4,但实际上当您 运行 您的代码时,它会给您 5、5、5、,5 , 5 因为你在打印达到 5 时写了 i
和 i
这就是它退出 for 循环的原因,但是你注意到我添加的代码,我通过 i
作为函数的参数,这样它会为我们保存值,当执行函数时它会写入 0, 1, 2, 3, 4