我最近遇到了一个相当严重的错误,其中代码通过JavaScript动态加载<select>。这个动态加载的<select>有一个预先选定的值。在IE6中,我们已经有代码来修复选中的<option>,因为有时<select>的selectedIndex值会与选中的<option>的index属性不同步,如下所示:

field.selectedIndex = element.index;

然而,这段代码没有工作。即使字段的selectedIndex设置正确,最终还是会选择错误的索引。但是,如果我在正确的时间插入alert()语句,则会选择正确的选项。考虑到这可能是某种时间问题,我尝试了一些以前在代码中见过的随机方法:

var wrapFn = (function() {
    var myField = field;
    var myElement = element;

    return function() {
        myField.selectedIndex = myElement.index;
    }
})();
setTimeout(wrapFn, 0);

这招奏效了!

我找到了解决问题的方法,但我不知道为什么这能解决我的问题,这让我感到不安。有人有官方解释吗?什么浏览器问题,我避免调用我的函数“稍后”使用setTimeout()?


当前回答

setTimout on 0在设置一个延迟承诺的模式中也非常有用,你想要立即返回:

myObject.prototype.myMethodDeferred = function() {
    var deferredObject = $.Deferred();
    var that = this;  // Because setTimeout won't work right with this
    setTimeout(function() { 
        return myMethodActualWork.call(that, deferredObject);
    }, 0);
    return deferredObject.promise();
}

其他回答

setTimeout()即使设置为0,也会在DOM元素加载之前为您争取一些时间。

看看这个:setTimeout

这样做的一个原因是将代码的执行推迟到单独的后续事件循环。在响应某种类型的浏览器事件(例如鼠标单击)时,有时有必要仅在处理完当前事件后执行操作。setTimeout()工具是最简单的方法。

编辑现在是2015年,我应该注意到还有requestAnimationFrame(),这并不完全相同,但它足够接近setTimeout(fn, 0),值得一提。

这是一个有老答案的老问题。我想重新审视这个问题,并回答为什么会发生这种情况,而不是为什么这种方法有用。

所以你有两个功能:

var f1 = function () {    
   setTimeout(function(){
      console.log("f1", "First function call...");
   }, 0);
};

var f2 = function () {
    console.log("f2", "Second call...");
};

然后按如下顺序调用它们f1();f2 ();看看第二个先执行。

原因如下:不可能让setTimeout的时间延迟为0毫秒。最小值由浏览器决定,不是0毫秒。历史上浏览器将这个最小值设置为10毫秒,但HTML5规范和现代浏览器将其设置为4毫秒。

如果嵌套级别大于5,并且超时时间小于4,则 将timeout增加为4。

同样来自mozilla:

要在现代浏览器中实现0毫秒超时,可以使用 window.postMessage()如下所述。

附注:信息是在阅读以下文章后获取的。

这做的另一件事是将函数调用推到堆栈的底部,防止递归调用函数时堆栈溢出。这具有while循环的效果,但允许JavaScript引擎触发其他异步计时器。

问题是您试图在一个不存在的元素上执行Javascript操作。元素还没有被加载,setTimeout()给了一个元素更多的时间,以以下方式加载:

setTimeout() causes the event to be ansynchronous therefore being executed after all the synchronous code, giving your element more time to load. Asynchronous callbacks like the callback in setTimeout() are placed in the event queue and put on the stack by the event loop after the stack of synchronous code is empty. The value 0 for ms as a second argument in function setTimeout() is often slightly higher (4-10ms depending on browser). This slightly higher time needed for executing the setTimeout() callbacks is caused by the amount of 'ticks' (where a tick is pushing a callback on the stack if stack is empty) of the event loop. Because of performance and battery life reasons the amount of ticks in the event loop are restricted to a certain amount less than 1000 times per second.