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

我怕爱的太早我们不能终老 提交于 2020-01-03 11:13:09

问题


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?


回答1:


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.




回答2:


You could use closure:

setTimeout((function(A){
               return function(){
                   whatsA(A);
               }; 
            })(A), 100);



回答3:


Of your three methods:

Option 1:

setTimeout(function() { whatsA(A); }, 100);

This one works everywhere and is simple. It's what I would recommend unless the variable A might change before the setTimeout function is called. If you need to freeze the value of A, then see my option 4 below.


Option 2:

setTimeout(whatsA, 100, A);

This only works in some browsers. Not recommended.


Option 3:

setTimeout('whatsA(' + A + ')', 100);

This is never recommended. Constructing code as a string and then evaluating it later is almost never the best solution.


I would recommend Option 4:

To freeze the value of A, you can create a closure using a self executing function:

A = 1;

function(A) {
    setTimeout(function() {whatsA(A);}, 100);
}(A);

A = 2;
function whatsA(X) { console.log(X); }


来源:https://stackoverflow.com/questions/10572673/how-can-i-pass-an-argument-to-a-function-called-using-settimeout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!