为什么在将函数作为参数传递时我必须省略括号?

时间:2012-07-09 21:21:27

标签: javascript

我试图解决为什么下面的代码在包含括号时会导致堆栈溢出,但是当它们被省略时却不会。

我将函数本身作为setTimeout的参数调用,它在没有parantheses的情况下工作,但当我添加它们时当然会失败。在函数之后添加()是我的直觉。只希望有人可以为我解决这个问题。 parans什么时候是可选的而不是?

案例1:

var a = 1;

function foo() {
    a++;
    document.write(a);
    setTimeout(foo(), 2000)
}​ 
// RangeError: Maximum call stack size exceeded

案例2:

var a = 1;

function foo() {
    a++;
    document.write(a);
    setTimeout(foo, 2000)
}​
// parens are omitted on foo function and it works. 

2 个答案:

答案 0 :(得分:11)

这个问题通常是在setTimeout时首先提出来的,但我认为重要的是要指出这里的行为并不是针对该功能的。您只需要了解括号的作用以及将它们关闭的含义。

假设以下功能:

function foo() {
    return 5;
}

考虑以下两个变量声明/赋值:

var one = foo();
var two = foo;

这些变量有什么价值?

在第一种情况下,我们执行 foo函数并将其返回值 - 数字5 - 分配给one。在第二种情况下,我们将foo本身 - 更准确地说是对foo的引用 - 分配给two。该功能永远不会执行。

凭借这些知识以及setTimeout期望作为其第一个参数引用到函数的理解,应该明白为什么第一个案例失败,但第二个案例有效。< / p>

当然,您执行的功能是对自身的递归调用,这会加剧您的问题。这将永远运行 - 对于永远的某些定义 - 因为没有基本情况来终止递归。

答案 1 :(得分:9)

写作

foo()

那时你实际上是在叫foo。当然然后再次调用foo()...直到你stackoverflow。

在案例2中,你有效地将“引用”传递给foo,说“以2s运行”。实际上并没有调用foo()。

因此,当您真正想要调用它时,请使用parens。不是当你想要引用它时。