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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With