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():Because
bind()is actually a function invocation, it reads the currentAvalue and returns a function with that value bound as an argument. If you find it hard to understand, try this:Note that
thisis kind of a lie here – you can safely passwindowas well.The first method is also acceptable, it just needs to be slightly improved:
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.