我正在查看Web应用程序中的一些现有代码。我看到了这个:
window.setTimeout(function () { ... })
这是否只是立即执行功能内容?
答案 0 :(得分:82)
它不一定会立即运行,也不会将延迟显式设置为0.原因是setTimeout从执行队列中删除了该函数,并且只有在JavaScript完成当前执行队列后才会调用它。
console.log(1);
setTimeout(function() {console.log(2)});
console.log(3);
console.log(4);
console.log(5);
//console logs 1,3,4,5,2
有关详细信息,请参阅http://javascriptweblog.wordpress.com/2010/06/28/understanding-javascript-timers/
答案 1 :(得分:20)
setTimeout
使用的最小延迟(根据HTML5为4毫秒,Firefox 3.6使用10毫秒)。 Mozilla开发人员中心documentation page对此进行了讨论。
答案 2 :(得分:1)
您缺少毫秒参数...
setTimeout(function() { /*something*/ }, 0);
0将延迟设置为0,但它实际上做的是让你的函数“跳转队列”浏览器执行列表。浏览器有很多事情要做,比如在页面上渲染对象,通过调用它,只要浏览器有一些循环,你的函数就会运行。
答案 3 :(得分:0)
简短的回答是不,它不一样。
MDN setTimeout documentation 中 delay
参数的说明是:
定时器在开始之前应该等待的时间,以毫秒为单位 执行指定的函数或代码。如果省略该参数, 使用值 0,表示“立即”执行,或更多 准确地说,下一个事件周期。请注意,在任何一种情况下,实际 延迟可能比预期的要长;请参阅延迟时间超过的原因 指定如下。
省略 delay
或使用 0
的值将在下一个事件周期中执行,但可能需要更长的时间。这是它与立即执行函数内容不同的第一个原因。例如:
document.getElementById("runNow").addEventListener("click", runNow);
document.getElementById("runNoDelay").addEventListener("click", runNoDelay);
function runNow() {
clearLog();
addLog("Start");
addLog("Hello");
addLog("End");
}
function runNoDelay() {
clearLog();
addLog("Start");
setTimeout(function() {
addLog("Hello");
});
addLog("End");
}
function clearLog() {
const log = document.getElementById("log");
while (log.lastElementChild) {
log.removeChild(log.lastElementChild);
}
}
function addLog(message) {
const newLine = document.createElement("pre");
newLine.textContent = message;
document.getElementById("log").appendChild(newLine);
}
<button id="runNow">Run Now</button>
<button id="runNoDelay">Run With No Delay</button>
<div id="log"></div>
请注意,在无延迟地使用 setTimeout
时,消息“End”出现在“Hello”之前。
即使延迟被省略或为 0
,也有可能导致延迟更长的原因,其中可能包括:
例如:
document.getElementById("run").addEventListener("click", run);
function run() {
clearLog();
const now = new Date().getMilliseconds();
setTimeout(function() {
timeout(0, now);
});
}
function clearLog() {
const log = document.getElementById("log");
while (log.lastElementChild) {
log.removeChild(log.lastElementChild);
}
}
function timeout(nestingLevel, last) {
const now = new Date().getMilliseconds();
logline(nestingLevel, now, last);
if (nestingLevel < 9) {
setTimeout(function() {
timeout(nestingLevel + 1, now);
});
}
}
function logline(nestingLevel, now, last) {
const newLine = document.createElement("pre");
newLine.textContent = `${nestingLevel} ${now - last}`;
document.getElementById("log").appendChild(newLine);
}
<button id="run">Run</button>
<pre>nesting level delay</pre>
<div id="log"></div>
(改编自 MDN 上的示例)。
注意延迟是 0
(或接近 0
),直到嵌套级别达到某个点。
同样重要的是要注意 setTimeout
是使用包装函数 (function () { ... }
) 调用的,这意味着 this
的值将与函数的内容相同立即被处决。
当嵌套级别为 4 时,Chrome(版本 92.0.4515.131)和 Firefox(版本 91.0)强制最小超时为 4 毫秒,如上例所示。
HTML Standard 表示“如果嵌套级别大于 5,并且超时小于 4,则将超时设置为 4”。
我的解释是这些浏览器过早地强制执行这个最小超时 2 个任务。应该是应用于嵌套级别为6(大于5)的第7个任务的调度。
在一天结束时,浏览器可以根据需要使用其他一些实现定义的时间长度,因此这是一个有趣但没有实际意义的问题。