我有一些JavaScript代码,看起来像:

function statechangedPostQuestion()
{
  //alert("statechangedPostQuestion");
  if (xmlhttp.readyState==4)
  {
    var topicId = xmlhttp.responseText;
    setTimeout("postinsql(topicId)",4000);
  }
}

function postinsql(topicId)
{
  //alert(topicId);
}

我得到一个错误,topicId没有定义 在我使用setTimeout()函数之前,一切都在工作。

我希望我的postinsql(topicId)函数在一段时间后被调用。 我该怎么办?


当前回答

取代

 setTimeout("postinsql(topicId)", 4000);

with

 setTimeout("postinsql(" + topicId + ")", 4000);

或者更好的是,用匿名函数替换字符串表达式

 setTimeout(function () { postinsql(topicId); }, 4000);

编辑:

Brownstone的评论是不正确的,这将按照预期工作,正如在Firebug控制台中运行它所演示的那样

(function() {
  function postinsql(id) {
    console.log(id);
  }
  var topicId = 3
  window.setTimeout("postinsql(" + topicId + ")",4000); // outputs 3 after 4 seconds
})();

请注意,我同意其他人的观点,即您应该避免将字符串传递给setTimeout,因为这将在字符串上调用eval(),而不是传递一个函数。

其他回答

@Jiri Vetyska感谢你的帖子,但你的例子有问题。 我需要传递的目标是悬停(这)到一个超时函数,我尝试了你的方法。在IE9测试-不工作。 我也做了一些研究,这里指出的第三个参数是使用的脚本语言。没有提到额外的参数。

所以,我遵循@meder的答案,用这段代码解决了我的问题:

$('.targetItemClass').hover(ItemHoverIn, ItemHoverOut);

function ItemHoverIn() {
 //some code here
}

function ItemHoverOut() {
    var THIS = this;
    setTimeout(
        function () { ItemHoverOut_timeout(THIS); },
        100
    );
}
function ItemHoverOut_timeout(target) {
    //do something with target which is hovered out
}

霍普,这对别人有用。

这是一个已经有“正确”答案的老问题,但我想我要提到另一种没有人在这里提到过的方法。这是从优秀的下划线库复制和粘贴:

_.delay = function(func, wait) {
  var args = slice.call(arguments, 2);
  return setTimeout(function(){ return func.apply(null, args); }, wait);
};

你可以传递尽可能多的参数给setTimeout调用的函数,作为一个额外的奖励(好吧,通常是一个奖励),传递给你的函数的参数的值在你调用setTimeout时被冻结,所以如果它们在setTimeout()被调用和超时之间的某个点上改变了值,嗯…这已经不再令人沮丧了:)

这里有一把小提琴,你可以明白我的意思。

这适用于所有浏览器(IE是一个奇怪的)

setTimeout( (function(x) {
return function() {
        postinsql(x);
    };
})(topicId) , 4000);

我知道它很老了,但我想加入我喜欢的味道。

我认为实现这一点的一种相当易读的方法是将topicId传递给一个函数,该函数反过来使用参数在内部引用主题ID。即使外部的topicId不久后将被更改,该值也不会改变。

var topicId = xmlhttp.responseText;
var fDelayed = function(tid) {
  return function() {
    postinsql(tid);
  };
}
setTimeout(fDelayed(topicId),4000);

或短:

var topicId = xmlhttp.responseText;
setTimeout(function(tid) {
  return function() { postinsql(tid); };
}(topicId), 4000);

有些答案是正确的,但令人费解。

四年后,我再次回答这个问题,因为我仍然会遇到过于复杂的代码来解决这个问题。有一个优雅的解决方案。

首先,在调用setTimeout时不要传入一个字符串作为第一个参数,因为它有效地调用了对缓慢的“eval”函数的调用。

那么如何将参数传递给超时函数呢?通过使用闭包:

settopic=function(topicid){
  setTimeout(function(){
    //thanks to closure, topicid is visible here
    postinsql(topicid);
  },4000);
}

...
if (xhr.readyState==4){
  settopic(xhr.responseText);
}

一些人建议在调用timeout函数时使用匿名函数:

if (xhr.readyState==4){
  setTimeout(function(){
    settopic(xhr.responseText);
  },4000);
}

语法是正确的。但是当settopic被调用时,也就是4秒之后,XHR对象可能就不一样了。因此,预绑定变量非常重要。