Let's consider this piece of JavaScript:
function Person(name) {
this.name = name;
}
Person.prototype.showName = function() {
alert(this.name);
}
var mike = new Person("mike");
//mike.showName();
window.name = "window";
I don't understand the difference between the behavior of
setTimeout(mike.showName(), 5000);
and
setTimeout(function(){
mike.showName();
}, 5000);
Why is the behavior different? It really confuses me. Thanks.
-
5I'm fairly certain the OP means "behavior" when he says "performance".Wayne– Wayne2011年04月02日 00:22:29 +00:00Commented Apr 2, 2011 at 0:22
4 Answers 4
Your question really has nothing at all to do with setTimeout. You simply need to understand the difference between a function call and a reference to a function.
Consider these four assignments:
var one = function() { mike.showName(); };
var two = mike.showName;
var three = mike.showName();
var four = (function() { mike.showName(); })();
The first two assign a reference to a function to their respective variables. The last two, however, call functions (that's what the parens are for) and assign their return values to the vars on the left-hand side.
How this relates to setTimeout:
The setTimeout function expects as its first argument a reference to a function, so either one or two above would be correct, but three and four would not. However, it is important to note that it is not, strictly speaking, a mistake to pass the return value of a function to setTimeout, although you'll frequently see that said.
This is perfectly fine, for example:
function makeTimeoutFunc(param) {
return function() {
// does something with param
}
}
setTimeout(makeTimeoutFunc(), 5000);
It has nothing to do with how setTimeout receives a function as its argument, but that it does.
2 Comments
mike.showName() says to run the function showName right now and pass whatever it returns as the callback to be executed in 5 seconds (which is nothing). However, passing function(){ mike.showName() } provides setTimeout with an anonymous function to run five seconds from now. Five seconds go by and the outer wrapper function is executed. It contains one line, which is the call to showName, which is executed at that time.If the accepted answer is just too long to read:
setTimeout(mike.showName(), 5000);
This will execute whatever mike.showName() returns after 5,000 milliseconds.
setTimeout(function(){ mike.showName(); }, 5000);
This will execute anonymous function after 5000 milliseconds that calls mike.showName() , the actual function.
Another way to achieve same effect:
setTimeout(mike.showName.bind(mike), 5000);
Comments
It's not a performance issue. One of the ways you showed simply doesn't work (it calls the function immediately instead of when the timeout fires).
setTimeout(mike.showName(), 5000); will execute the showName function and sets its return value as the timeout callback which won't work.
setTimeout(function(){ mike.showName(); }, 5000); creates an anonymous function and sets this as the timeout callback. When the timeout fires, the function is called and calls your showName() function.
Fyi, setTimeout('mike.showName();', 5000); would also work. But don't do that - it's just as bad as using eval(). Besides that it makes your code less readable since the code in the string cannot be syntax-highlighted.
2 Comments
() it's not called - the function itself is passed.setTimeout(mike.showName(), 5000); executes mike.showName() immediately and passes the return value to setTimeout()
setTimeout(function(){ mike.showName(); }, 5000); passes a pointer to the function instead. That way setTimeout can execute the function, rather than it's return value.