如何将参数传递给setTimeout()回调?

时间:2021-05-26 23:00:27

I have some JavaScript code that looks like:

我有一些JavaScript代码是这样的:

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

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

I get a error that topicId is not defined Everything was working before i used the setTimeout() function.

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

I want my postinsql(topicId) function to be called after some time. What should i do?

我希望在一段时间后调用postinsql(topicId)函数。我应该做什么?

19 个解决方案

#1


910  

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

You need to feed an anonymous function as a parameter instead of a string, the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient. This is the proper solution, don't ever rely on passing a string as a 'function' when using setTimeout() or setInterval(), it's slower because it has to be evaluated and it just isn't right.

您需要将一个匿名函数作为参数来提供,而不是字符串,后一种方法甚至不能在ECMAScript规范中工作,但是浏览器是很宽松的。这是正确的解决方案,在使用setTimeout()或setInterval()时,不要依赖于传递字符串作为“函数”,它的速度较慢,因为它必须被评估,而且它是不正确的。

UPDATE:

更新:

As Hobblin said in his comments to the question, now you can pass arguments to the function inside setTimeout using Function.prototype.bind()

正如Hobblin在对这个问题的评论中所说的,现在您可以使用Function.prototype.bind()将参数传递给setTimeout中的函数

Example:

例子:

setTimeout(postinsql.bind(null, topicId), 4000);

#2


548  

In modern browsers, the "setTimeout" receives a third parameter that is sent as parameter to the internal function at the end of the timer.

在现代浏览器中,“setTimeout”接收第三个参数,该参数作为参数发送到计时器末尾的内部函数。

Example:

例子:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

More details:

更多的细节:

#3


111  

After doing some research and testing, the only correct implementation is:

在做了一些研究和测试之后,唯一正确的实现是:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

setTimeout will pass all extra parameters to your function so they can be processed there.

setTimeout将把所有额外的参数传递给您的函数,以便在那里进行处理。

The anonymous function can work for very basic stuff, but within instance of a object where you have to use "this", there is no way to make it work. Any anonymous function will change "this" to point to window, so you will lose your object reference.

匿名函数可以用于非常基本的东西,但是在一个对象的实例中,您必须使用“this”,没有办法使它工作。任何匿名函数都会将“this”更改为指向窗口,因此您将丢失对象引用。

#4


43  

This is a very old question with an already "correct" answer but I thought I'd mention another approach that nobody has mentioned here. This is copied and pasted from the excellent underscore library:

这是一个非常古老的问题,已经有了一个“正确”的答案,但我想我应该提到另一个没有人提到过的方法。这是从优秀的下划线库复制粘贴的:

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

You can pass as many arguments as you'd like to the function called by setTimeout and as an added bonus (well, usually a bonus) the value of the arguments passed to your function are frozen when you call setTimeout, so if they change value at some point between when setTimeout() is called and when it times out, well... that's not so hideously frustrating anymore :)

你可以通过尽可能多的你想要调用的函数的参数setTimeout和还有一个额外的好处(通常一个奖金)的值传递给函数的参数被冻结当你叫setTimeout,所以如果他们改变价值之间在某些时候当setTimeout()次时,嗯…这已经不再令人沮丧了:)

Here's a fiddle where you can see what I mean - http://jsfiddle.net/thedavidmeister/7t2bV/

这里有一个小提琴,你可以看到我的意思——http://jsfiddle.net/thedavidmeister/7t2bV/。

#5


34  

I recently came across the unique situation of needing to use a setTimeout in a loop. Understanding this can help you understand how to pass parameters to setTimeout.

最近,我遇到了需要在循环中使用setTimeout的独特情况。理解这一点可以帮助您理解如何将参数传递给setTimeout。

Method 1

方法1

Use forEach and Object.keys, as per Sukima's suggestion:

使用forEach和对象。根据Sukima的建议:

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

I recommend this method.

我推荐这个方法。

Method 2

方法2

Use bind:

使用绑定:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

JSFiddle:http://jsfiddle.net/MsBkW/

Method 3

方法3

Or if you can't use forEach or bind, use an IIFE:

或者如果你不能使用forEach或bind,使用IIFE:

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

Method 4

方法4

But if you don't care about IE < 10, then you could use Fabio's suggestion:

但是如果你不关心IE < 10,那么你可以使用Fabio的建议:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

Method 5 (ES6)

方法5(ES6)

Use a block scoped variable:

使用一个块范围变量:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

Though I would still recommend using Object.keys with forEach in ES6.

尽管我仍然建议使用对象。在ES6中有forEach的键。

#6


22  

Hobblin already commented this on the question, but it should be an answer really!

Hobblin已经对这个问题发表了评论,但这应该是一个答案!

Using Function.prototype.bind() is the cleanest and most flexible way to do this (with the added bonus of being able to set the this context):

使用函数.prototype.bind()是最干净和最灵活的方法(可以设置此上下文的额外好处):

setTimeout(postinsql.bind(null, topicId), 4000);

For more information see these MDN links:
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

要了解更多信息,请参见这些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。

#7


13  

Some answers are correct but convoluted.

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

I am answering this again, 4 years later, because I still run into overly complex code to solve exactly this question. There IS an elegant solution.

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

First of all, do not pass in a string as the first parameter when calling setTimeout because it effectively invokes a call to the slow "eval" function.

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

So how do we pass in a parameter to a timeout function? By using closure:

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

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

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

Some have suggested using anonymous function when calling the timeout function:

有些人在调用超时功能时建议使用匿名函数:

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

The syntax works out. But by the time settopic is called, i.e. 4 seconds later, the XHR object may not be the same. Therefore it's important to pre-bind the variables.

的语法。但是,在被调用时,即4秒之后,XHR对象可能就不一样了。因此,预先绑定变量很重要。

#8


9  

Replace

取代

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

with

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

or better still, replace the string expression with an anonymous function

或者更好的方法是用一个匿名函数替换字符串表达式。

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

EDIT:

编辑:

Brownstone's comment is incorrect, this will work as intended, as demonstrated by running this in the Firebug console

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

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

Note that I'm in agreeance with others that you should avoid passing a string to setTimeout as this will call eval() on the string and instead pass a function.

请注意,我与其他人一致,您应该避免将字符串传递给setTimeout,因为这将调用字符串中的eval(),而不是传递函数。

#9


6  

My answer:

我的回答:

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

Explanation:

解释:

The anonymous function created returns another anonymous function. This function has access to the originally passed topicId, so it will not make an error. The first anonymous function is immediately called, passing in topicId, so the registered function with a delay has access to topicId at the time of calling, through closures.

创建的匿名函数返回另一个匿名函数。这个函数可以访问最初通过的topicId,所以它不会出错。第一个匿名函数被立即调用,传入topicId,因此,带有延迟的注册函数可以在调用时通过闭包访问topicId。

OR

This basically converts to:

这基本上转换:

setTimeout(function() {
  postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);

EDIT: I saw the same answer, so look at his. But I didn't steal his answer! I just forgot to look. Read the explanation and see if it helps to understand the code.

我看到了相同的答案,所以看看他的。但是我没有偷他的答案!我只是忘了看。阅读解释,看它是否有助于理解代码。

#10


5  

The easiest cross browser solution for supporting parameters in setTimeout:

在setTimeout中支持参数的最简单的跨浏览器解决方案:

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

If you don't mind not supporting IE 9 and lower:

如果你不介意不支持ie9和更低:

setTimeout(postinsql, 4000, topicId);

如何将参数传递给setTimeout()回调?

如何将参数传递给setTimeout()回调?

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

#11


3  

I know it's old but I wanted to add my (preferred) flavour to this.

我知道它很旧,但我想把我的(喜欢的)味道添加到它里面。

I think a pretty readable way to achieve this is to pass the topicId to a function, which in turn uses the argument to reference the topic ID internally. This value won't change even if topicId in the outside will be changed shortly after.

我认为实现这一目标的一种非常可读的方法是将topicId传递给函数,而函数反过来使用参数在内部引用主题ID。这个值不会改变,即使在外面的topicId很快会被改变。

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

or short:

或短:

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

#12


3  

this works in all browsers (IE is an oddball)

这在所有浏览器中都有效(IE是个古怪的人)

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

#13


2  

Note that the reason topicId was "not defined" per the error message is that it existed as a local variable when the setTimeout was executed, but not when the delayed call to postinsql happened. Variable lifetime is especially important to pay attention to, especially when trying something like passing "this" as an object reference.

请注意,在错误消息中,topicId“没有定义”的原因是,当setTimeout被执行时,它作为一个局部变量存在,而不是当延迟调用postinsql发生时。变量生存期尤其需要注意,特别是在尝试类似传递“this”作为对象引用时。

I heard that you can pass topicId as a third parameter to the setTimeout function. Not much detail is given but I got enough information to get it to work, and it's successful in Safari. I don't know what they mean about the "millisecond error" though. Check it out here:

我听说您可以将topicId作为第三个参数传递给setTimeout函数。虽然没有给出太多的细节,但我得到了足够的信息让它工作,而且它在Safari中是成功的。我不知道他们说的“毫秒误差”是什么意思。检查一下:

http://www.howtocreate.co.uk/tutorials/javascript/timers

http://www.howtocreate.co.uk/tutorials/javascript/timers

#14


2  

How i resolved this stage ?

我是如何解决这个问题的?

just like that :

就像这样:

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

setTimeout wait a reference to a function, so i created it in a closure, which interprete my data and return a function with a good instance of my data !

setTimeout等待一个函数的引用,所以我在一个闭包中创建了它,它解释了我的数据,并返回了一个具有良好实例数据的函数!

Maybe you can improve this part :

也许你可以改进这部分:

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

I tested it on chrome, firefox and IE and it execute well, i don't know about performance but i needed it to be working.

我在chrome、firefox和IE上测试了它,它执行得很好,我不知道性能,但我需要它工作。

a sample test :

样品测试:

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

Maybe you can change the signature to make it more complient :

也许你可以更改签名,使它更符合要求:

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

And finaly to answer the original question :

最后回答了最初的问题:

 myNass_setTimeOut( postinsql, 4000, topicId );

Hope it can help !

希望它能帮上忙!

ps : sorry but english it's not my mother tongue !

对不起,但是英语不是我的母语!

#15


2  

The answer by David Meister seems to take care of parameters that may change immediately after the call to setTimeout() but before the anonymous function is called. But it's too cumbersome and not very obvious. I discovered an elegant way of doing pretty much the same thing using IIFE (immediately inviked function expression).

David Meister的答案似乎是处理在调用setTimeout()之后可能会立即更改的参数,但是在调用匿名函数之前。但它太笨重,不太明显。我发现了一种用IIFE(立即inviked函数表达式)做几乎相同的事情的优雅方法。

In the example below, the currentList variable is passed to the IIFE, which saves it in its closure, until the delayed function is invoked. Even if the variable currentList changes immediately after the code shown, the setInterval() will do the right thing.

在下面的例子中,currentList变量被传递给IIFE,它在它的闭包中保存它,直到调用延迟函数为止。即使变量currentList在代码显示后立即发生变化,setInterval()也会做正确的事情。

Without this IIFE technique, the setTimeout() function will definitely get called for each h2 element in the DOM, but all those calls will see only the text value of the last h2 element.

如果没有这个IIFE技术,setTimeout()函数肯定会被DOM中的每个h2元素调用,但是所有这些调用只会看到最后一个h2元素的文本值。

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>

#16


0  

I think you want:

我认为你想要的:

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

#17


0  

@Jiri Vetyska thanks for the post, but there is something wrong in your example. I needed to pass the target which is hovered out (this) to a timed out function and I tried your approach. Tested in IE9 - does not work. I also made some research and it appears that as pointed here the third parameter is the script language being used. No mention about additional parameters.

@Jiri Vetyska谢谢你的帖子,但是你的例子有问题。我需要传递一个目标,这个目标是一个超时的函数,我尝试了你的方法。在IE9中测试——不工作。我还做了一些研究,似乎在这里,第三个参数是使用的脚本语言。没有提到其他参数。

So, I followed @meder's answer and solved my issue with this code:

所以,我遵从了@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
}

Hope, this is usefull for someone else.

希望,这对其他人来说是有用的。

#18


0  

As there is a problem with the third optonal parameter in IE and using closures prevents us from changing the variables (in a loop for example) and still achieving the desired result, I suggest the following solution.

由于IE中的第三个op音调参数存在问题,并且使用闭包阻止我们更改变量(例如,在循环中),并且仍然达到预期的结果,我建议如下解决方案。

We can try using recursion like this:

我们可以尝试使用递归式:

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

We need to make sure that nothing else changes these variables and that we write a proper recursion condition to avoid infinite recursion.

我们需要确保没有其他任何东西改变这些变量,我们编写一个适当的递归条件来避免无限递归。

#19


0  

In general, if you need to pass a function as a callback with specific parameters, you can use higher order functions. This is pretty elegant with ES6:

一般来说,如果您需要传递函数作为带有特定参数的回调函数,则可以使用更高的顺序函数。这是非常优雅的ES6:

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

Or if someFunction is first order:

或者如果某个函数是一阶的:

setTimeout(() => someFunction(params), 1000); 

#1


910  

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

You need to feed an anonymous function as a parameter instead of a string, the latter method shouldn't even work per the ECMAScript specification but browsers are just lenient. This is the proper solution, don't ever rely on passing a string as a 'function' when using setTimeout() or setInterval(), it's slower because it has to be evaluated and it just isn't right.

您需要将一个匿名函数作为参数来提供,而不是字符串,后一种方法甚至不能在ECMAScript规范中工作,但是浏览器是很宽松的。这是正确的解决方案,在使用setTimeout()或setInterval()时,不要依赖于传递字符串作为“函数”,它的速度较慢,因为它必须被评估,而且它是不正确的。

UPDATE:

更新:

As Hobblin said in his comments to the question, now you can pass arguments to the function inside setTimeout using Function.prototype.bind()

正如Hobblin在对这个问题的评论中所说的,现在您可以使用Function.prototype.bind()将参数传递给setTimeout中的函数

Example:

例子:

setTimeout(postinsql.bind(null, topicId), 4000);

#2


548  

In modern browsers, the "setTimeout" receives a third parameter that is sent as parameter to the internal function at the end of the timer.

在现代浏览器中,“setTimeout”接收第三个参数,该参数作为参数发送到计时器末尾的内部函数。

Example:

例子:

var hello = "Hello World";
setTimeout(alert, 1000, hello);

More details:

更多的细节:

#3


111  

After doing some research and testing, the only correct implementation is:

在做了一些研究和测试之后,唯一正确的实现是:

setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

setTimeout will pass all extra parameters to your function so they can be processed there.

setTimeout将把所有额外的参数传递给您的函数,以便在那里进行处理。

The anonymous function can work for very basic stuff, but within instance of a object where you have to use "this", there is no way to make it work. Any anonymous function will change "this" to point to window, so you will lose your object reference.

匿名函数可以用于非常基本的东西,但是在一个对象的实例中,您必须使用“this”,没有办法使它工作。任何匿名函数都会将“this”更改为指向窗口,因此您将丢失对象引用。

#4


43  

This is a very old question with an already "correct" answer but I thought I'd mention another approach that nobody has mentioned here. This is copied and pasted from the excellent underscore library:

这是一个非常古老的问题,已经有了一个“正确”的答案,但我想我应该提到另一个没有人提到过的方法。这是从优秀的下划线库复制粘贴的:

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

You can pass as many arguments as you'd like to the function called by setTimeout and as an added bonus (well, usually a bonus) the value of the arguments passed to your function are frozen when you call setTimeout, so if they change value at some point between when setTimeout() is called and when it times out, well... that's not so hideously frustrating anymore :)

你可以通过尽可能多的你想要调用的函数的参数setTimeout和还有一个额外的好处(通常一个奖金)的值传递给函数的参数被冻结当你叫setTimeout,所以如果他们改变价值之间在某些时候当setTimeout()次时,嗯…这已经不再令人沮丧了:)

Here's a fiddle where you can see what I mean - http://jsfiddle.net/thedavidmeister/7t2bV/

这里有一个小提琴,你可以看到我的意思——http://jsfiddle.net/thedavidmeister/7t2bV/。

#5


34  

I recently came across the unique situation of needing to use a setTimeout in a loop. Understanding this can help you understand how to pass parameters to setTimeout.

最近,我遇到了需要在循环中使用setTimeout的独特情况。理解这一点可以帮助您理解如何将参数传递给setTimeout。

Method 1

方法1

Use forEach and Object.keys, as per Sukima's suggestion:

使用forEach和对象。根据Sukima的建议:

var testObject = {
    prop1: 'test1',
    prop2: 'test2',
    prop3: 'test3'
};

Object.keys(testObject).forEach(function(propertyName, i) {
    setTimeout(function() {
        console.log(testObject[propertyName]);
    }, i * 1000);
});

I recommend this method.

我推荐这个方法。

Method 2

方法2

Use bind:

使用绑定:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }.bind(this, propertyName), i++ * 1000);
}

JSFiddle: http://jsfiddle.net/MsBkW/

JSFiddle:http://jsfiddle.net/MsBkW/

Method 3

方法3

Or if you can't use forEach or bind, use an IIFE:

或者如果你不能使用forEach或bind,使用IIFE:

var i = 0;
for (var propertyName in testObject) {
    setTimeout((function(propertyName) {
        return function() {
            console.log(testObject[propertyName]);
        };
    })(propertyName), i++ * 1000);
}

Method 4

方法4

But if you don't care about IE < 10, then you could use Fabio's suggestion:

但是如果你不关心IE < 10,那么你可以使用Fabio的建议:

var i = 0;
for (var propertyName in testObject) {
    setTimeout(function(propertyName) {
        console.log(testObject[propertyName]);
    }, i++ * 1000, propertyName);
}

Method 5 (ES6)

方法5(ES6)

Use a block scoped variable:

使用一个块范围变量:

let i = 0;
for (let propertyName in testObject) {
    setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);
}

Though I would still recommend using Object.keys with forEach in ES6.

尽管我仍然建议使用对象。在ES6中有forEach的键。

#6


22  

Hobblin already commented this on the question, but it should be an answer really!

Hobblin已经对这个问题发表了评论,但这应该是一个答案!

Using Function.prototype.bind() is the cleanest and most flexible way to do this (with the added bonus of being able to set the this context):

使用函数.prototype.bind()是最干净和最灵活的方法(可以设置此上下文的额外好处):

setTimeout(postinsql.bind(null, topicId), 4000);

For more information see these MDN links:
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

要了解更多信息,请参见这些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。

#7


13  

Some answers are correct but convoluted.

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

I am answering this again, 4 years later, because I still run into overly complex code to solve exactly this question. There IS an elegant solution.

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

First of all, do not pass in a string as the first parameter when calling setTimeout because it effectively invokes a call to the slow "eval" function.

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

So how do we pass in a parameter to a timeout function? By using closure:

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

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

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

Some have suggested using anonymous function when calling the timeout function:

有些人在调用超时功能时建议使用匿名函数:

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

The syntax works out. But by the time settopic is called, i.e. 4 seconds later, the XHR object may not be the same. Therefore it's important to pre-bind the variables.

的语法。但是,在被调用时,即4秒之后,XHR对象可能就不一样了。因此,预先绑定变量很重要。

#8


9  

Replace

取代

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

with

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

or better still, replace the string expression with an anonymous function

或者更好的方法是用一个匿名函数替换字符串表达式。

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

EDIT:

编辑:

Brownstone's comment is incorrect, this will work as intended, as demonstrated by running this in the Firebug console

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

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

Note that I'm in agreeance with others that you should avoid passing a string to setTimeout as this will call eval() on the string and instead pass a function.

请注意,我与其他人一致,您应该避免将字符串传递给setTimeout,因为这将调用字符串中的eval(),而不是传递函数。

#9


6  

My answer:

我的回答:

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

Explanation:

解释:

The anonymous function created returns another anonymous function. This function has access to the originally passed topicId, so it will not make an error. The first anonymous function is immediately called, passing in topicId, so the registered function with a delay has access to topicId at the time of calling, through closures.

创建的匿名函数返回另一个匿名函数。这个函数可以访问最初通过的topicId,所以它不会出错。第一个匿名函数被立即调用,传入topicId,因此,带有延迟的注册函数可以在调用时通过闭包访问topicId。

OR

This basically converts to:

这基本上转换:

setTimeout(function() {
  postinsql(topicId); // topicId inside higher scope (passed to returning function)
}, 4000);

EDIT: I saw the same answer, so look at his. But I didn't steal his answer! I just forgot to look. Read the explanation and see if it helps to understand the code.

我看到了相同的答案,所以看看他的。但是我没有偷他的答案!我只是忘了看。阅读解释,看它是否有助于理解代码。

#10


5  

The easiest cross browser solution for supporting parameters in setTimeout:

在setTimeout中支持参数的最简单的跨浏览器解决方案:

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

If you don't mind not supporting IE 9 and lower:

如果你不介意不支持ie9和更低:

setTimeout(postinsql, 4000, topicId);

如何将参数传递给setTimeout()回调?

如何将参数传递给setTimeout()回调?

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout

#11


3  

I know it's old but I wanted to add my (preferred) flavour to this.

我知道它很旧,但我想把我的(喜欢的)味道添加到它里面。

I think a pretty readable way to achieve this is to pass the topicId to a function, which in turn uses the argument to reference the topic ID internally. This value won't change even if topicId in the outside will be changed shortly after.

我认为实现这一目标的一种非常可读的方法是将topicId传递给函数,而函数反过来使用参数在内部引用主题ID。这个值不会改变,即使在外面的topicId很快会被改变。

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

or short:

或短:

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

#12


3  

this works in all browsers (IE is an oddball)

这在所有浏览器中都有效(IE是个古怪的人)

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

#13


2  

Note that the reason topicId was "not defined" per the error message is that it existed as a local variable when the setTimeout was executed, but not when the delayed call to postinsql happened. Variable lifetime is especially important to pay attention to, especially when trying something like passing "this" as an object reference.

请注意,在错误消息中,topicId“没有定义”的原因是,当setTimeout被执行时,它作为一个局部变量存在,而不是当延迟调用postinsql发生时。变量生存期尤其需要注意,特别是在尝试类似传递“this”作为对象引用时。

I heard that you can pass topicId as a third parameter to the setTimeout function. Not much detail is given but I got enough information to get it to work, and it's successful in Safari. I don't know what they mean about the "millisecond error" though. Check it out here:

我听说您可以将topicId作为第三个参数传递给setTimeout函数。虽然没有给出太多的细节,但我得到了足够的信息让它工作,而且它在Safari中是成功的。我不知道他们说的“毫秒误差”是什么意思。检查一下:

http://www.howtocreate.co.uk/tutorials/javascript/timers

http://www.howtocreate.co.uk/tutorials/javascript/timers

#14


2  

How i resolved this stage ?

我是如何解决这个问题的?

just like that :

就像这样:

setTimeout((function(_deepFunction ,_deepData){
    var _deepResultFunction = function _deepResultFunction(){
          _deepFunction(_deepData);
    };
    return _deepResultFunction;
})(fromOuterFunction, fromOuterData ) , 1000  );

setTimeout wait a reference to a function, so i created it in a closure, which interprete my data and return a function with a good instance of my data !

setTimeout等待一个函数的引用,所以我在一个闭包中创建了它,它解释了我的数据,并返回了一个具有良好实例数据的函数!

Maybe you can improve this part :

也许你可以改进这部分:

_deepFunction(_deepData);

// change to something like :
_deepFunction.apply(contextFromParams , args); 

I tested it on chrome, firefox and IE and it execute well, i don't know about performance but i needed it to be working.

我在chrome、firefox和IE上测试了它,它执行得很好,我不知道性能,但我需要它工作。

a sample test :

样品测试:

myDelay_function = function(fn , params , ctxt , _time){
setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.call(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// the function to be used :
myFunc = function(param){ console.log(param + this.name) }
// note that we call this.name

// a context object :
myObjet = {
    id : "myId" , 
    name : "myName"
}

// setting a parmeter
myParamter = "I am the outer parameter : ";

//and now let's make the call :
myDelay_function(myFunc , myParamter  , myObjet , 1000)

// this will produce this result on the console line :
// I am the outer parameter : myName

Maybe you can change the signature to make it more complient :

也许你可以更改签名,使它更符合要求:

myNass_setTimeOut = function (fn , _time , params , ctxt ){
return setTimeout((function(_deepFunction ,_deepData, _deepCtxt){
            var _deepResultFunction = function _deepResultFunction(){
                //_deepFunction(_deepData);
                _deepFunction.apply(  _deepCtxt , _deepData);
            };
        return _deepResultFunction;
    })(fn , params , ctxt)
, _time) 
};

// and try again :
for(var i=0; i<10; i++){
   myNass_setTimeOut(console.log ,1000 , [i] , console)
}

And finaly to answer the original question :

最后回答了最初的问题:

 myNass_setTimeOut( postinsql, 4000, topicId );

Hope it can help !

希望它能帮上忙!

ps : sorry but english it's not my mother tongue !

对不起,但是英语不是我的母语!

#15


2  

The answer by David Meister seems to take care of parameters that may change immediately after the call to setTimeout() but before the anonymous function is called. But it's too cumbersome and not very obvious. I discovered an elegant way of doing pretty much the same thing using IIFE (immediately inviked function expression).

David Meister的答案似乎是处理在调用setTimeout()之后可能会立即更改的参数,但是在调用匿名函数之前。但它太笨重,不太明显。我发现了一种用IIFE(立即inviked函数表达式)做几乎相同的事情的优雅方法。

In the example below, the currentList variable is passed to the IIFE, which saves it in its closure, until the delayed function is invoked. Even if the variable currentList changes immediately after the code shown, the setInterval() will do the right thing.

在下面的例子中,currentList变量被传递给IIFE,它在它的闭包中保存它,直到调用延迟函数为止。即使变量currentList在代码显示后立即发生变化,setInterval()也会做正确的事情。

Without this IIFE technique, the setTimeout() function will definitely get called for each h2 element in the DOM, but all those calls will see only the text value of the last h2 element.

如果没有这个IIFE技术,setTimeout()函数肯定会被DOM中的每个h2元素调用,但是所有这些调用只会看到最后一个h2元素的文本值。

<script>
  // Wait for the document to load.
  $(document).ready(function() {
  $("h2").each(function (index) {

    currentList = $(this).text();

    (function (param1, param2) {
        setTimeout(function() {
            $("span").text(param1 + ' : ' + param2 );
        }, param1 * 1000);

    })(index, currentList);
  });
</script>

#16


0  

I think you want:

我认为你想要的:

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

#17


0  

@Jiri Vetyska thanks for the post, but there is something wrong in your example. I needed to pass the target which is hovered out (this) to a timed out function and I tried your approach. Tested in IE9 - does not work. I also made some research and it appears that as pointed here the third parameter is the script language being used. No mention about additional parameters.

@Jiri Vetyska谢谢你的帖子,但是你的例子有问题。我需要传递一个目标,这个目标是一个超时的函数,我尝试了你的方法。在IE9中测试——不工作。我还做了一些研究,似乎在这里,第三个参数是使用的脚本语言。没有提到其他参数。

So, I followed @meder's answer and solved my issue with this code:

所以,我遵从了@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
}

Hope, this is usefull for someone else.

希望,这对其他人来说是有用的。

#18


0  

As there is a problem with the third optonal parameter in IE and using closures prevents us from changing the variables (in a loop for example) and still achieving the desired result, I suggest the following solution.

由于IE中的第三个op音调参数存在问题,并且使用闭包阻止我们更改变量(例如,在循环中),并且仍然达到预期的结果,我建议如下解决方案。

We can try using recursion like this:

我们可以尝试使用递归式:

var i = 0;
var hellos = ["Hello World1!", "Hello World2!", "Hello World3!", "Hello World4!", "Hello World5!"];

if(hellos.length > 0) timeout();

function timeout() {                
    document.write('<p>' + hellos[i] + '<p>');
    i++;
    if (i < hellos.length)
        setTimeout(timeout, 500);
}

We need to make sure that nothing else changes these variables and that we write a proper recursion condition to avoid infinite recursion.

我们需要确保没有其他任何东西改变这些变量,我们编写一个适当的递归条件来避免无限递归。

#19


0  

In general, if you need to pass a function as a callback with specific parameters, you can use higher order functions. This is pretty elegant with ES6:

一般来说,如果您需要传递函数作为带有特定参数的回调函数,则可以使用更高的顺序函数。这是非常优雅的ES6:

const someFunction = (params) => () => {
  //do whatever
};

setTimeout(someFunction(params), 1000);

Or if someFunction is first order:

或者如果某个函数是一阶的:

setTimeout(() => someFunction(params), 1000);