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

新手上路,请多包涵

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

 window.onload = initAll();

window.onload = initAll;

请解释其背后的原理。

原文由 Dean 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 375
2 个回答
> window.onload = initAll();
>
> ```

这会立即 **执行** `initAll()` **并将** **函数的返回值** 分配给 `window.onload` 。这通常 **不是** 您想要的。 `initAll()` 必须返回一个函数才有意义。

> ```
>  window.onload = initAll;
>
> ```

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

您可能还会看到类似这样的内容:

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

”`

这将创建一个新函数, 调用时立即 调用 initAll 。这里括号是必要的,因为“ _调用 initAll 立即_”部分起作用。但是,因为它被包装在一个函数中,所以在调用外部函数本身之前什么都不会执行,并且您将该外部函数的引用分配给 window.onload ,所以 initAll 也将被执行在加载事件上。

原文由 Pekka 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

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

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

这同样可以写成:

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

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

所以现在要区分分配:

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

在定义ret变量的时候, Multiply 被执行,返回值赋值 ret 等于12。

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

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

Now, at the point of defining ret , ret becomes your Multiply function as opposed to being the result obtained from your Multiply function.调用 ret() 将导致执行你的 Multiply 函数,你可以像调用 Multiply(operator, operand) 一样调用它:

 var out = ret(3, 4);

是相同的

var out = Multiply(3, 4);

您实际上已经说过,您将使用 ret 作为 Multiply() 的代表。当调用 ret 时,我们实际上指的是 Multiply 函数。

回到你的 window.onload 。把这个想象成:

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

initAll = function() {
    return 12;
}

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

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

 window.onload = initAll();

这还不如说:

 window.onload = 12;

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

所以:

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

被替换为:

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

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

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

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

另一个可能更好地证明的例子是:

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

无论当时是什么时候 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 c and d assignments exactly as we could call currentTime() ?

原文由 BenAlabaster 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题