0

考虑以下命名函数:

function f() {
    return f.apply(this, arguments);
}

如果您正常调用此函数,则会按预期导致堆栈溢出。不是很有趣。所以让我们做一些魔术:

var g = f, f = alert;

现在,如果您调用f它,它将只是alert第一个参数。但是,如果您调用g它,它仍然alert是第一个参数。发生了什么?调用不应该g导致堆栈溢出吗?

我的理解是,在函数内部f(现在g),变量f不再绑定到f. 它成为一个自由变量。因此f,变量内部f现在指向alert

为什么会这样?我希望命名函数中的函数名始终引用函数本身。我没有抱怨。它实际上很酷。我只是好奇。

4

2 回答 2

4

当你这样做时:

var g = f

这实际上与以下内容相同:

var g = function () {
    return f.apply(this, arguments);
}

但是,由于您重新分配f它不再指向原始函数,它现在指向alert. 看起来它正在按设计工作。

于 2014-01-06T02:42:16.867 回答
1

正如其他答案所提到的,它是按设计的。基本上,除了提升之外,声明是这样做的:

var f = function () {
    return f.apply(this, arguments);
}

也就是说, 的值f不是在声明时解析,而是在函数调用时解析。这就是为什么你看到你所看到的。

但是有一种方法可以强制它按照您想要的方式运行:使用命名函数表达式。命名函数表达式看起来像声明,但不是因为函数被声明为表达式。

例如,在下面:

var ff = function f () {
    return f.apply(this, arguments);
}

的值f在声明时绑定,并且不受重新分配的影响。在命名函数表达式中,函数名仅在表达式内部定义,因此其行为更像是闭包而不是变量。

于 2014-01-06T02:59:39.917 回答