Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pass an argument to a function called using setTimeout?

I want to pass an argument to a function called using setTimeout. I have found these three options:

A = 1;
// Method 1: closure things
setTimeout(function() { whatsA(A); }, 100);
// Method 2: third argument (same result with [A])
setTimeout(whatsA, 100, A);
// Method 3: eval
setTimeout('whatsA(' + A + ')', 100);
A = 2;
function whatsA(X) { console.log(X); }

This shows 2, undefined, and 1 in Internet Explorer 9.

Method 1: Clearly, I would not like the argument to be changed after passing it (certainly in the case of simple integers).

Method 2: This would be perfect if only Internet Explorer supported it.

Method 3: This seems to be the only choice. But it seems rather less pretty than the others, passing something to be evaluated rather than a function.

Is there a better way?

like image 886
Mark Avatar asked May 13 '12 14:05

Mark


1 Answers

The best solution I can think of is using bind():

A = 1;
setTimeout(whatsA.bind(this, A), 100);

Because bind() is actually a function invocation, it reads the current A value and returns a function with that value bound as an argument. If you find it hard to understand, try this:

var newFun = whatsA.bind(this, 42);
newFun()

Note that this is kind of a lie here - you can safely pass window as well.


The first method is also acceptable, it just needs to be slightly improved:

A = 1;
var tmpA = A;
setTimeout(function() { whatsA(tmpA); }, 100);

What you are observing is actually a feature, not a bug. You are passing a closure to setTimeout() referencing local variable. JavaScript is clever enough to delay access to that variable up to the moment when the function is actually called. And since you have modified the variable, you see the most recent version.


The second method is deprecated won't work in any browser.


Third method is terrible, avoid passing string to setTimeout(), there is always a better solution.

like image 131
Tomasz Nurkiewicz Avatar answered Nov 04 '22 10:11

Tomasz Nurkiewicz