我有一些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参数的最简单的跨浏览器解决方案:
setTimeout(function() {
postinsql(topicId);
}, 4000)
如果你不介意不支持ie9及以下版本:
setTimeout(postinsql, 4000, topicId);
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
Hobblin已经就这个问题发表了评论,但它确实应该是一个答案!
使用Function.prototype.bind()是最干净和最灵活的方法(能够设置this上下文的额外奖励):
setTimeout(postinsql.bind(null, topicId), 4000);
欲了解更多信息,请参阅这些MDN链接:
https://developer.mozilla.org/en/docs/DOM/window.setTimeout#highlighter_547041
https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Function/bind#With_setTimeout
有些答案是正确的,但令人费解。
四年后,我再次回答这个问题,因为我仍然会遇到过于复杂的代码来解决这个问题。有一个优雅的解决方案。
首先,在调用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对象可能就不一样了。因此,预绑定变量非常重要。
我知道这个问题已经问了10年了,但是,如果你一直滚动到这里,我认为你仍然面临着一些问题。Meder Omuraliev的解决方案是最简单的,可能对我们大多数人都有帮助,但对于那些不想有任何约束的人来说,下面是:
setTimeout使用Param
setTimeout(function(p){
//p == param1
},3000,param1);
使用立即调用的函数表达式
let param1 = 'demon';
setTimeout(function(p){
// p == 'demon'
},2000,(function(){
return param1;
})()
);
问题的解决方法
function statechangedPostQuestion()
{
//alert("statechangedPostQuestion");
if (xmlhttp.readyState==4)
{
setTimeout(postinsql,4000,(function(){
return xmlhttp.responseText;
})());
}
}
function postinsql(topicId)
{
//alert(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(),而不是传递一个函数。
这是一个已经有“正确”答案的老问题,但我想我要提到另一种没有人在这里提到过的方法。这是从优秀的下划线库复制和粘贴:
_.delay = function(func, wait) {
var args = slice.call(arguments, 2);
return setTimeout(function(){ return func.apply(null, args); }, wait);
};
你可以传递尽可能多的参数给setTimeout调用的函数,作为一个额外的奖励(好吧,通常是一个奖励),传递给你的函数的参数的值在你调用setTimeout时被冻结,所以如果它们在setTimeout()被调用和超时之间的某个点上改变了值,嗯…这已经不再令人沮丧了:)
这里有一把小提琴,你可以明白我的意思。