现在,我通常使用()
调用一个函数(不需要参数),如下所示:
myFunction(); //there's empty parens
除了jQuery调用,我可以逃脱:
$('#foo').bind('click', myFunction); //no parens
精细。但最近我在SO上看到了这条评论here:
“考虑使用setTimeout(monitor, 100);
代替setTimeout('monitor()', 100);
.Eval是邪恶的:)”
糟糕!我们真的eval()
在这里输了一个字符串吗?我想我并不真正理解“调用”函数的意义和含义。有关调用和引用函数的真正规则是什么?
答案 0 :(得分:44)
在JavaScript函数中是第一类对象。这意味着您可以将函数作为参数传递给函数,或者将它们视为变量。
假设我们正在谈论一个函数hello
,
function hello() {
alert('yo');
}
当我们写简单时
hello
我们指的是不执行它内容的函数。但是当我们在函数名称之后添加parens ()
时,
hello()
然后我们实际上调用了将在屏幕上警告“你”的功能。
jQuery中的bind
方法接受事件类型(字符串)和函数作为其参数。在您的示例中,您将传递类型 - “单击”和实际函数作为参数。
你见过Inception吗?考虑这个可能使事情更清晰的人为例子。由于函数是JavaScript中的第一类对象,我们可以在函数内传递和返回函数。因此,让我们创建一个在调用时返回函数的函数,并且返回的函数在调用时也会返回另一个函数。
function reality() {
return function() {
return function() {
alert('in a Limbo');
}
};
}
此处reality
是一个函数,reality()
是一个函数,reality()()
也是一个函数。但是reality()()()
不是函数,而只是undefined
因为我们没有从最里面的函数返回一个函数(我们没有返回任何东西)。
因此,对于reality
函数示例,您可以将以下任何内容传递给jQuery的bind。
$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());
答案 1 :(得分:7)
您的jQuery bind
示例与setTimeout(monitor, 100);
类似,您将函数对象的引用作为参数传递。
应避免将字符串传递给setTimeout
/ setInterval
方法,原因与在不必要时应避免eval
和Function
构造函数相同。
作为字符串传递的代码将在全局执行上下文中进行评估和运行,这可以为您提供“范围问题”,请考虑以下示例:
// 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"
})();
上例中的第一个setTimeout
调用将执行全局f
函数,因为已计算的代码无法访问匿名函数的本地词法范围。
如果在第二个setTimeout
调用中将函数对象的引用传递给setTimeout
方法 - 将在当前作用域中引用完全相同的函数。
答案 2 :(得分:3)
你在jQuery示例中没有像在第二个setTimeout
示例中那样做 - 在你的代码中传递函数并绑定click
事件。
在第一个setTimout
示例中,monitor
函数被传入并且可以直接调用,在第二个中,sting monitor()
被传入并且需要{{1 }}编
传递函数时,使用函数名称。调用它时,您需要使用eval
。
Eval将调用传入的内容,因此成功调用函数需要()
。
答案 3 :(得分:2)
首先,“()”不是函数名称的一部分。 它是用于进行函数调用的语法。
首先,通过使用函数声明将函数绑定到标识符名称:
function x() {
return "blah";
}
...或使用函数表达式:
var x = function() {
return "blah";
};
现在,只要您想运行此功能,就可以使用parens:
x();
setTimeout函数接受函数的两者和标识符,或者接受字符串作为第一个参数...
setTimeout(x, 1000);
setTimeout("x()", 1000);
如果您提供标识符,则它将作为函数调用。 如果你提供一个字符串,那么它将被评估(执行)。
第一种方法(提供标识符)是首选......