What's the meaning of "()" in a function call?
Now, I usually call a function (that requires no arguments) with 开发者_开发问答()
like this:
myFunction(); //there's empty parens
Except in jQuery calls where I can get away with:
$('#foo').bind('click', myFunction); //no parens
Fine. But recently I saw this comment here on SO:
"Consider using setTimeout(monitor, 100);
instead of setTimeout('monitor()', 100);
. Eval is evil :)"
Yikes! Are we really eval()
-ing a string here? I guess I don't really understand the significance and implications of 'calling' a function. What are the real rules about calling and referring to functions?
In JavaScript functions are first-class objects. That means you can pass functions around as parameters to a function, or treat them as variables in general.
Let's say we are talking about a function hello
,
function hello() {
alert('yo');
}
When we simply write
hello
we are referring to the function which doesn't execute it's contents. But when we add the parens ()
after the function name,
hello()
then we are actually calling the function which will alert "yo" on the screen.
The bind
method in jQuery accepts the type of event (string) and a function as its arguments. In your example, you are passing the type - "click" and the actual function as an argument.
Have you seen Inception? Consider this contrived example which might make things clearer. Since functions are first-class objects in JavaScript, we can pass and return a function from within a function. So let's create a function that returns a function when invoked, and the returned function also returns another function when invoked.
function reality() {
return function() {
return function() {
alert('in a Limbo');
}
};
}
Here reality
is a function, reality()
is a function, and reality()()
is a function as well. However reality()()()
is not a function, but simply undefined
as we are not returning a function (we aren't returning anything) from the innermost function.
So for the reality
function example, you could have passed any of the following to jQuery's bind.
$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());
Your jQuery bind
example is similar to setTimeout(monitor, 100);
, you are passing a reference of a function object as an argument.
Passing a string to the setTimeout
/setInterval
methods should be avoided for the same reasons you should avoid eval
and the Function
constructor when it is unnecessary.
The code passed as a string will be evaluated and run in the global execution context, which can give you "scope issues", consider the following example:
// a global function
var f = function () {
alert('global');
};
(function () {
// a local function
var f = function() {
alert('local');
};
setTimeout('f()', 100); // will alert "global"
setTimeout(f, 100); // will alert "local"
})();
The first setTimeout
call in the above example, will execute the global f
function, because the evaluated code has no access to the local lexical scope of the anonymous function.
If you pass the reference of a function object to the setTimeout
method -like in the second setTimeout
call- the exact same function you refer in the current scope will be executed.
You are not doing the same thing in your jQuery example as in the second setTimeout
example - in your code you are passing the function and binding the click
event.
In the first setTimout
example, the monitor
function is passed in and can be invoked directly, in the second, the sting monitor()
is passed in and needs to be eval
ed.
When passing a function around, you use the function name. When invoking it, you need to use the ()
.
Eval will invoke what is passed in, so a ()
is required for a successful function invocation.
First of all, "()" is not part of the function name. It is syntax used to make function calls.
First, you bind a function to an identifier name by either using a function declaration:
function x() {
return "blah";
}
... or by using a function expression:
var x = function() {
return "blah";
};
Now, whenever you want to run this function, you use the parens:
x();
The setTimeout function accepts both and identifier to a function, or a string as the first argument...
setTimeout(x, 1000);
setTimeout("x()", 1000);
If you supply an identifier, then it will get called as a function. If you supply an string, than it will be evaluated (executed).
The first method (supplying an identifier) is preferred ...
精彩评论