我最近遇到了一个相当严重的错误,其中代码通过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()?


当前回答

由于传递给它的持续时间为0,我认为这是为了从执行流中删除传递给setTimeout的代码。因此,如果它是一个可能需要一段时间的函数,它不会阻止后续代码的执行。

其他回答

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

所以你有两个功能:

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()如下所述。

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

//When need "new a", setTimeout(fn, 0) is useful, when need to wait some action. Example: var a = function (){console.log('a');}; var b = function(){setTimeout(b, 100);}; //wait some action before override this function //without setTimeout: console.log('no setTimeout: b.toString():', b.toString()); b(); //"b" is an old function console.log('no setTieout: a.toString(): ', a.toString()); a(); //and "a" is not overrided setTimeout(//but with setTimeout(fn, 0): function(){ console.log('After timeout 0, b.toString(): ', b.toString()); b(); //"b" is a new function console.log('After timeout 0, a.toString(): ', a.toString()); a(); //and "a" is overrided }, 0 ); //override var "b", which was been undefined b = function (){ a = function(){console.log('new a');}; }

通过调用setTimeout,您可以给页面时间来响应用户正在做的任何事情。这对于在页面加载期间运行的函数特别有用。

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

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

看看这个:setTimeout