函数调用和函数引用有什么区别?

41

我有以下函数:

function hello() {
 alert("hi!");
}

看一下这段代码:

var elem = document.getElementById("btn");
elem.onclick = hello;

我的问题可能有点难以理解,所以请耐心等待: 此段代码与普通调用有何区别,或者说这段代码为什么需要对函数变量进行引用而不是常规调用?(hello();)

我如何知道在哪里应该给一个函数引用,在什么时候应该实际调用它?


我可能错了,对于这些动态语言还很陌生(刚开始学习Python),但我认为引用是当你想要创建一个别名来调用该函数时,而调用则是字面上的调用。例如,var = hello,然后在任何调用var()的地方,它与调用hello()相同。 - SGM1
6个回答

52

好的,onclick 属性期望一个函数引用,在元素被点击时执行该函数。通常有以下两种方式:

element.onclick = funcRef;
或者
element.onclick = function () {
    funcRef();
};

(当然,最好使用 addEventListener 和 attachEvent

注意两者都是指向函数的引用,而不是调用。

当某个东西期望一个引用时,你不会调用它...你给它分配一个引用(第一个例子)。

当您想特别调用一个函数时,您使用()来调用它(第二个例子)。但请注意,在第二个示例中,仍有一个分配给onclick的函数引用 - 它只是一个匿名函数。

可能更重要的部分:

有些人认为您想要这样做:

element.onclick = funcRef();

但是这会立即执行函数(由于括号()的存在),并将其返回值赋给onclick。除非返回值一个函数,否则这不是你想要的。

我认为故事的寓意在于,当你想/需要立即执行某些操作时,请调用该函数。如果该函数需要存储以供将来使用,则不要调用它。


10
“立即执行”位非常重要。 - Wex
@Wex 哈哈,是的,我似乎低估了它。正在思考如何更深入地扩展它。 - Ian
有一个有趣的边界情况:element.onclick = getClickHandler() - John Dvorak
@JanDvorak 可能不是太明显,但我已经包含了“除非返回值是一个函数,否则这不是你想要的。”我不想深入讨论它,以免困扰提问者。 - Ian
你能详细说明一下如何/为什么使用addEventListener和attachEvent吗?或者指导我去哪里可以阅读相关内容? - frrlod
2
@frrlod 当然可以!https://dev59.com/qGw15IYBdhLWcg3w3vle - Ian

30

你现在想让它立即执行吗?那就调用它。

a=hello() 的意思是“尽快调用hello(),并将其返回值设置为a”。

另一方面,a=hello 的意思是“ahello的别名。如果你调用a(),你得到的结果与调用hello()相同”。

你使用后者进行回调等操作,其中你想告诉浏览器在事件发生后要执行什么。例如,你可能想说“当用户点击时调用hello()”(如示例中所示)。或者,“当AJAX查询返回结果时,在返回的数据上调用callback()函数”。


19

我应该在什么地方给这个函数引用,而什么时候才需要调用它呢?

你现在需要让函数运行吗?

那就加上()来执行它。

你是否需要将函数引用起来以便稍后再调用它?

不要加上()。


3
几乎所有 JavaScript 语句都有一个返回值。除非有特别说明,否则调用 JavaScript 中的函数时将返回 undefined。因此,在这个赋值语句中调用您的函数只有在它返回一个函数的情况下才有意义:
function hello() {
    return function() {
        alert("hi!");
    }
}

elem.onclick = hello();

3

hello()表示你调用该函数,这意味着该函数将直接执行。

而当你使用elem.onclick = hello时,这被称为回调。其中hello不会直接执行,而只有在触发某个事件时才会执行(在此情况下是在元素上单击时)


2

无论如何调用,你需要在某个地方引用你的函数。这里的区别在于,你没有显式地调用hello函数。你正在将对该函数的引用分配给elem DOM节点的onclick事件处理程序,以便当该节点的onclick被触发时,将调用你的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接