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

Dea*_*ean 102 javascript

我注意到调用带有空括号的函数或根本没有任何括号时的区别.但是,我没有向函数传递任何参数,所以我想知道,有什么区别:

window.onload = initAll();
Run Code Online (Sandbox Code Playgroud)

window.onload = initAll;
Run Code Online (Sandbox Code Playgroud)

请解释其背后的原理.

Pek*_*ica 157

window.onload = initAll();
Run Code Online (Sandbox Code Playgroud)

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

window.onload = initAll;
Run Code Online (Sandbox Code Playgroud)

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

  • 这里重要的是,函数是JavaScript中的第一类对象. (18认同)

Ben*_*ter 135

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

我不会用,window.onload因为有点人为的证明.我将使用简单的乘法函数来演示:

function Multiply(operator, operand) {
    return operator * operand;
}
Run Code Online (Sandbox Code Playgroud)

这同样可以写成:

Multiply = function(operator, operand) {
    return operator * operand;
}
Run Code Online (Sandbox Code Playgroud)

虽然在第一个例子中,暗示可能并不明显,但第二个例子更清楚地表明我们正在为一个被调用的变量分配一个具有2个参数Multiply的函数,并且这个函数作为赋值的概念在整个JavaScript中是通用的.这是一个小例子,表明函数是"一等公民",也就是说,它们可以传递,就像我们传递价值一样.

所以现在分配的差异:

var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);
Run Code Online (Sandbox Code Playgroud)

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

让我们以另一种方式尝试:

var operator = 3;
var operand = 4;
var ret = Multiply;
Run Code Online (Sandbox Code Playgroud)

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

var out = ret(3, 4);
Run Code Online (Sandbox Code Playgroud)

是相同的

var out = Multiply(3, 4);
Run Code Online (Sandbox Code Playgroud)

你已经有效地说过你将ret作为代表使用Multiply().在打电话时ret,我们真的指的是这个Multiply功能.

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

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

initAll = function() {
    return 12;
}
Run Code Online (Sandbox Code Playgroud)

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

现在打电话给initAll()我们说的是:

window.onload = initAll();
Run Code Online (Sandbox Code Playgroud)

不妨说:

window.onload = 12;
Run Code Online (Sandbox Code Playgroud)

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

所以:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}
Run Code Online (Sandbox Code Playgroud)

替换为:

window.onload = function() {
    return 12;
}
Run Code Online (Sandbox Code Playgroud)

所以任何调用window.onload都会执行你的initAll函数而不是window.onload最初的函数.您已使用新功能替换了原始功能.

事实上,你可以同样写:

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

另一个可能表现得更好的例子是:

var d = new Date();
var currentTime = d.getTime();
Run Code Online (Sandbox Code Playgroud)

无论当时的时间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
Run Code Online (Sandbox Code Playgroud)

请注意我们如何打电话给b()我们cd我们可以调用的作业currentTime()


Pet*_*ley 16

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

所以,当你这样做的时候

window.onload = initAll;
Run Code Online (Sandbox Code Playgroud)

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

当你这样做

window.onload = initAll();
Run Code Online (Sandbox Code Playgroud)

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


And*_*ris 10

initAll 是对函数值的引用,并且括号运算符附加到函数名RUNS这个函数对象.

所以,如果你做的事情

a = initAll
Run Code Online (Sandbox Code Playgroud)

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

a = initAll()
Run Code Online (Sandbox Code Playgroud)

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


gar*_*mac 6

我迟到了6年但我觉得这可以解释得比上面的答案简单得多.

这是TLDR ; 或鸟瞰调用使用函数时,不使用()

让我们以此函数为例:

function foo(){
return 123;
}
Run Code Online (Sandbox Code Playgroud)

如果你记录"foo" - 没有 ()

console.log(foo); 

---outout------
function foo(){
return 123;
}
Run Code Online (Sandbox Code Playgroud)

不使用()的手段获取函数本身.如果您希望将其作为回调传递,则可以执行此操作.


如果你记录"foo()" - ()

console.log(foo());
-----output-----
 123
Run Code Online (Sandbox Code Playgroud)

使用()后一个功能是指执行功能,并返回它的值.