考虑以下命名函数:
function f() {
return f.apply(this, arguments);
}
如果正常调用此函数,则会导致堆栈溢出,如预期的那样。不是很有趣。让我们做一些魔术:
var g = f, f = alert;
现在,如果你致电f
,它只会alert
第一个参数。但是,如果您致电g
,它仍然会alert
第一个参数。发生了什么?不应该调用g
会导致堆栈溢出吗?
我理解的是,在函数f
(现在为g
)内,变量f
不再绑定到f
。它变成了一个自由变量。因此,在f
内,变量f
现在指向alert
。
为什么会这样?我希望命名函数中的函数名始终引用函数本身。我没有抱怨。它真的很酷。我只是好奇。
答案 0 :(得分:4)
当你这样做时:
var g = f
这实际上与:
相同var g = function () {
return f.apply(this, arguments);
}
但是,由于您重新分配了f
,它不再指向原始函数,现在它指向alert
。看起来它按设计工作。
答案 1 :(得分:1)
如其他答案所述,它是按照设计的。基本上,除了吊装之外,声明是这样做的:
var f = function () {
return f.apply(this, arguments);
}
也就是说,f
的值未在声明处解析,而是在函数调用期间解析。这就是为什么你会看到你所看到的。
但是有一种方法可以强制它按照你想要的方式行事:使用named function expression。命名函数表达式看起来像声明,但不是由于函数被声明为表达式。
例如,在以下内容中:
var ff = function f () {
return f.apply(this, arguments);
}
f
的值在声明中受到约束,并且不受重新分配的影响。在命名函数表达式中,函数名仅在表达式中定义,因此更像是闭包而不是变量。