简体   繁体   English

函数调用中“()”的含义是什么?

[英]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: 除了jQuery调用,我可以逃脱:

$('#foo').bind('click', myFunction); //no parens

Fine. 精细。 But recently I saw this comment here on SO: 但最近我看到这个评论这里的SO:

"Consider using setTimeout(monitor, 100); instead of setTimeout('monitor()', 100); . Eval is evil :)" “考虑使用setTimeout(monitor, 100);而不是setTimeout('monitor()', 100); ;. Eval是邪恶的:)”

Yikes! 哎呀! Are we really eval() -ing a string here? 我们真的在这里eval()字符串吗? 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. 在JavaScript中,函数是第一类对象。 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 , 假设我们正在谈论一个函数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, 但是当我们在函数名之后添加parens ()

hello()

then we are actually calling the function which will alert "yo" on the screen. 然后我们实际上调用了将在屏幕上提醒“yo”的功能。

The bind method in jQuery accepts the type of event (string) and a function as its arguments. jQuery中的bind方法接受事件类型(字符串)和函数作为其参数。 In your example, you are passing the type - "click" and the actual function as an argument. 在您的示例中,您将传递类型 - “单击”和实际函数作为参数。

Have you seen Inception? 你见过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. 由于函数是JavaScript中的第一类对象,我们可以在函数内传递和返回函数。 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. 这里的reality是一种功能, reality()是一种功能,而reality()()也是一种功能。 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. 然而, reality()()()不是一个函数,而是简单地undefined因为我们没有从最里面的函数返回一个函数(我们没有返回任何东西)。

So for the reality function example, you could have passed any of the following to jQuery's bind. 因此,对于reality函数示例,您可以将以下任何内容传递给jQuery的bind。

$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());

Your jQuery bind example is similar to setTimeout(monitor, 100); 你的jQuery bind示例类似于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. 应该避免将字符串传递给setTimeout / setInterval方法,原因与避免使用evalFunction构造eval原因相同。

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. 上例中的第一个setTimeout调用将执行全局f函数,因为计算出的代码无法访问匿名函数的本地词法范围。

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. 如果在第二个setTimeout调用中将函数对象的引用传递给setTimeout方法,则将执行您在当前范围中引用的完全相同的函数。

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. 您在jQuery示例中没有像在第二个setTimeout示例中那样做同样的事情 - 在您的代码中,您传递函数并绑定click事件。

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. 在第一个setTimout示例中, monitor函数被传入并可以直接调用,在第二个中,sting monitor()被传入并需要进行eval

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. Eval将调用传入的内容,因此成功调用函数需要a ()

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: 现在,只要你想运行这个函数,就可以使用parens:

x();

The setTimeout function accepts both and identifier to a function, or a string as the first argument... setTimeout函数接受函数的两者和标识符,或作为第一个参数的字符串...

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 ... 第一种方法(提供标识符)是首选...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM