我对setTimeout感到有点困惑。我想确认以下代码的输出是否一直是:
inside abc
inside sample
代码:
function abc() {
xyz();
// interactions and modifications in DOM
$("#id1").append("something");
$("#id2").val("set something");
$("#id3").after("create some dynamic element");
// 10 to 20 interaction more...
console.log('inside abc');
}
function xyz() {
setTimeout(function() {
sample();
},0);
}
function sample() {
console.log('inside sample')
}
如果有人可以通过调用堆栈解释整个流程,那将会很棒。
答案 0 :(得分:3)
是的,它总会有输出。
在执行上下文清除之前,将不会调用setTimeout
内的回调 - 即当前正在执行的代码序列已完成。
这意味着即使你做了
setTimeout(function () { console.log("1 second!"); }, 1000);
var start = +new Date();
while ((+new Date()) - start < 5000) {}
1 second!
不会在5秒后记录。
答案 1 :(得分:3)
setTimeout()将异步运行。所以输出应始终相同:
inside abc
inside sample
Javascript在内部管理所有异步任务的事件队列。每次在完成当前执行块后检查其异步队列。
答案 2 :(得分:2)
是的,控制台输出将始终相同。 setTimeout的回调函数在清除调用它的上下文后异步执行。调用setTimeout时,它会将其回调函数放在堆栈上并返回当前执行上下文。完成后(在您的示例中,当abc完全执行时),将执行回调函数,在您的示例中,它基本上会立即调用sample。所以你的代码输出永远不会有所不同。
如果你在调用xyz之前在abc中的某处放置了一个更长的setTimeout函数,那么可以看到setTimeout的回调本身是异步执行的这一事实:
function abc() {
setTimeout(function(){
console.log('wait')
},1000);
xyz();
console.log('inside abc');
}
function xyz() {
setTimeout(function(){
sample();
} ,0);
}
function sample() {
console.log('inside sample');
}
abc();
...您的控制台将记录:
inside abc
inside sample
wait
要保持样本的执行,直到更长的超时完成,您需要将setTimeout调用样本放在更长的setTimeout中。
如果setTimeout的回调行为不同,很可能是由于意外传递了函数调用而不是函数指针,如下所示:
setTimeout(sample(),0);
而不是
setTimeout(sample,0)
此外,如果您不知道(或其他人),您可以添加
debugger;
在您的Javascript代码中的任何位置,然后使用开发工具运行代码以查看当时的callstack(在Chrome中,它位于&#39; Sources&#39;右侧面板中)。