在 JavaScript 中,如果我调用带括号的函数会有所不同吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3246928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:51:16  来源:igfitidea点击:

In JavaScript, does it make a difference if I call a function with parentheses?

javascript

提问by Dean

I noticed a difference when calling a function with empty parentheses, or without any parentheses at all. However, I am not passing any arguments to the function so I wondered, what would be the difference between:

我注意到在调用带有空括号或根本没有任何括号的函数时有所不同。但是,我没有将任何参数传递给函数,所以我想知道这两者之间有什么区别:

window.onload = initAll();

and

window.onload = initAll;

Please explain the principle behind it.

请解释其背后的原理。

回答by Pekka

window.onload = initAll();
window.onload = initAll();

This executesinitAll()straight awayand assigns the function's return valueto window.onload. This is usually notwhat you want. initAll()would have to return a function for this to make sense.

执行initAll()直线距离和分配函数的返回值window.onload。这通常不是您想要的。initAll()必须返回一个函数才能使其有意义。

window.onload = initAll;
window.onload = initAll;

this assigns the actual functionto window.onload- this is possible because in JavaScript, as @Felix says, functions are first class objects - without executing it. initAllwill be executed by the load event.

这将实际函数分配给window.onload- 这是可能的,因为在 JavaScript 中,正如@Felix 所说,函数是第一类对象 - 不执行它。initAll将由加载事件执行。

回答by BenAlabaster

What Pekka says is correct, but I want to elaborate a little with an example that will help explain to someone who doesn't fully understand function pointers or delegates.

Pekka 说的是正确的,但我想用一个例子来详细说明一下,这将有助于向不完全理解函数指针或委托的人解释。

I won't use window.onloadbecause that's a bit contrived to demonstrate. I'll use a simple multiply function to demo instead:

我不会使用,window.onload因为这有点人为地展示。我将使用一个简单的乘法函数来演示:

function Multiply(operator, operand) {
    return operator * operand;
}

This could equally be written:

这同样可以写成:

Multiply = function(operator, operand) {
    return operator * operand;
}

While in the first example, the implication may not be obvious, the second example shows more clearly that we're assigning a function which has 2 parameters to a variable called Multiply, and this concept of functions as assignments is common throughout JavaScript. This is a small demonstration of the fact that functions are "first class citizens", that is, they can be passed around exactly as if we were passing around values.

虽然在第一个示例中,含义可能并不明显,但第二个示例更清楚地表明我们将一个具有 2 个参数的函数分配给名为 的变量Multiply,并且这种将函数作为赋值的概念在整个 JavaScript 中都很常见。这是函数是“一等公民”这一事实的一个小例子,也就是说,它们可以像传递值一样传递。

So now to the difference of assignment:

所以现在是分配的区别:

var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);

At the point of defining the ret variable, Multiplyis executed and the return value is assigned - retbecomes equal to 12.

在定义 ret 变量时,Multiply执行并分配返回值 -ret变为等于 12。

Let's try that again a different way:

让我们以不同的方式再试一次:

var operator = 3;
var operand = 4;
var ret = Multiply;

Now, at the point of defining ret, retbecomes your Multiplyfunction as opposed to being the result obtained from your Multiplyfunction. Calls to ret()will cause your Multiplyfunction to be executed, and you can call it exactly as if you'd called Multiply(operator, operand):

现在,在定义ret,ret成为您的Multiply功能,而不是从您的Multiply功能中获得的结果。调用ret()将导致您的Multiply函数被执行,您可以完全像调用 一样调用它Multiply(operator, operand)

var out = ret(3, 4);

is the same as

是相同的

var out = Multiply(3, 4);

You have effectively said that you are going to use retas a delegate for Multiply(). When calling ret, we're really referring to the Multiplyfunction.

您已经有效地表示您ret将用作Multiply(). 调用 时ret,我们实际上指的是Multiply函数。

Back to your window.onload. Think of this as:

回到你的window.onload. 把它想象成:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

initAll = function() {
    return 12;
}

So as you can see, window.onloadis a function just like any other function, there's nothing special about it. You can assign it a value, assign it a function, null it out if you wish - the point is that there's nothing any more special about window.onloadthan there is about your own function. The only slightly different thing is that it gets called by the window when it's loaded. [Disclaimer: I've never actually nulled out window functions, so I'm not sure if this will cause negative repercussions. One would hope they check to see if a function is assigned before calling it i.e. if (window.onload) window.onload();].

所以正如你所看到的,window.onload是一个函数,就像任何其他函数一样,没有什么特别之处。您可以为它分配一个值,为它分配一个函数,如果您愿意,可以将其归零 - 重点是没有什么window.onload比您自己的函数更特别的了。唯一稍有不同的是它在加载时被窗口调用。[免责声明:我从来没有真正取消过窗口函数,所以我不确定这是否会导致负面影响。人们希望他们在调用一个函数之前检查它是否被赋值,即if (window.onload) window.onload();]。

Now calling initAll()what we're saying is:

现在调用initAll()我们所说的是:

window.onload = initAll();

which might as well say:

这也可以说:

window.onload = 12;

But when we say initAllwithout the parentheses, what we're really saying is: I want to replace whatever my window.onload function is, with a new function - i.e. I want to replace it with my initAllfunction, so that any calls to window.onloadruns my initAllcode.

但是当我们说不initAll带括号时,我们真正说的是:我想用一个新函数替换我的 window.onload 函数 - 即我想用我的initAll函数替换它,以便任何调用window.onload运行我的initAll代码。

So:

所以:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

is replaced with:

替换为:

window.onload = function() {
    return 12;
}

So any call to window.onloadwill execute your initAllfunction instead of whatever window.onloadwas originally. You have replaced the original function with your new function.

因此,任何调用都window.onload将执行您的initAll函数,而不是window.onload最初的函数。您已用新函数替换了原始函数。

In fact, you couldequally write:

事实上,你同样可以这样写:

window.onload = function() {
    //Write all your init code right in here instead of having a separate 
    //initAll function.
}

Another example that may demonstrate better is this:

另一个可以更好地展示的例子是:

var d = new Date();
var currentTime = d.getTime();

Whatever the time was at the time dis defined ends up assigned to currentTime. Great, but that's only useful if we want to find out what time the function containing that code was called - i.e. at page load time. What if we want the current time any time that currentTimeis called?

无论当时d定义的时间是什么,最终都会分配给currentTime. 很好,但只有当我们想知道包含该代码的函数是在什么时间被调用时才有用 - 即在页面加载时。如果我们想要currentTime被调用的任何时间的当前时间怎么办?

var currentTime = function() {
    var d = new Date();
    return d.getTime();
}

var a = currentTime(); //The current time at the point a is defined...
var b = currentTime;   //b is a functional reference to currentTime...
var c = b(); //The current time when variable c is defined
var d = c; //The current time when variable c was defined

Notice how we call b()in our cand dassignments exactly as we could call currentTime()?

请注意我们如何完全按照我们可以调用的方式调用b()我们的cd赋值currentTime()

回答by Peter Bailey

Functions in javascript are first-class citizens, and as such, can be assigned to other variables or passed around as arguments.

javascript 中的函数是一等公民,因此可以分配给其他变量或作为参数传递。

So, when you do

所以,当你做

window.onload = initAll;

You are setting the onloadproperty of the windowobject to reference the initAllfunction itself.

您正在设置对象的onload属性window以引用initAll函数本身。

When you do

当你做

window.onload = initAll();

You are setting the onloadproperty to hold the return valueof initAll, since it will execute in place on that line.

您正在设置onload属性以保存initAll的返回值,因为它将在该行上执行。

回答by Andris

initAllis a reference to a function value and the brackets operator appended to the function name RUNS this function object.

initAll是对函数值的引用,附加到函数名称的括号运算符运行此函数对象。

So if you do something like

所以如果你做类似的事情

a = initAll

then awill become the same as initAll- for example you can do a()- but with

然后a将变得与initAll- 例如你可以做a()- 但与

a = initAll()

the variable awill get the return value of the executed initAllfunction

该变量a将获取执行initAll函数的返回值

回答by garrettmac

I'm 6 years late but I feel this could have been explained a lot simpler than the above answers.

我迟到了 6 年,但我觉得这可以比上述答案更简单地解释。

So here is the TLDR; or bird's eye viewwhen calling functions using and not using ()'s

所以这是TLDR;或使用和不使用's调用函数时的鸟瞰图()

Lets take this function for example:

让我们以这个函数为例:

function foo(){
return 123;
}


if you log "foo" - without()

如果您登录“foo” -没有()

console.log(foo); 

---outout------
function foo(){
return 123;
}

Using no ()means to fetch the function itself. You would do this if you want it to be passed along as a callback.

不使用任何()方法来获取函数本身。如果您希望它作为回调传递,您可以这样做。



if you log "foo()" - with()

如果您记录“foo()” -()

console.log(foo());
-----output-----
 123

Using ()after a function means to execute the function and return it's value.

使用()后的功能的手段来执行功能,并返回它的值