简体   繁体   English

为什么JavaScript中命名函数中的函数名称不再引用该函数本身?

[英]Why does the function name inside a named function in JavaScript no longer refer to the function itself?

Consider the following named function: 考虑以下命名函数:

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

If you call this function normally it would result in a stack overflow as expected. 如果正常调用此函数,则将导致堆栈溢出。 Not very interesting. 不太有趣。 So let's do some magic: 因此,让我们做一些魔术:

var g = f, f = alert;

Now if you call f it will simply alert the first argument. 现在,如果调用f ,它将仅alert第一个参数。 However if you call g it will still alert the first argument. 但是,如果您调用g ,它将仍然alert第一个参数。 What's happening? 发生了什么? Shouldn't calling g result in a stack overflow? 调用g不应该导致堆栈溢出吗?

What I understand is that inside the function f (now g ) the variable f is no longer bound to f . 据我了解,在函数f (现在为g )中,变量f不再绑定到f It becomes a free variable. 它成为一个自由变量。 Hence inside f the variable f now points to alert . 因此,在f内部,变量f现在指向alert

Why does this happen? 为什么会这样? I would expect the function name inside a named function to always refer to the function itself. 我希望命名函数中的函数名称总是引用函数本身。 I'm not complaining. 我没有抱怨。 It's actually pretty cool. 实际上很酷。 I'm just curious. 我只是好奇。

When you do: 当您这样做时:

var g = f

This is effectively the same as: 这实际上与以下内容相同:

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

However, since you reassigned f it no longer points to the original function, it now points to alert . 但是,由于您已重新分配f因此它不再指向原始功能,因此现在指向alert Looks like it's working as designed. 看起来它正在按设计工作。

As mentioned by other answers, it's as designed. 如其他答案所述,它是设计好的。 Basically, apart from hoisting, the declaration is doing this: 基本上,除了吊装之外,声明还这样做:

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

That is to say, the value of f is not resolved at the declaration but rather during the function call. 也就是说, f的值不是在声明时解析的,而是在函数调用期间解析的。 Which is why you're seeing what you're seeing. 这就是为什么您看到自己所看到的。

But there is a way to force it to behave the way you want: use a named function expression . 但是有一种方法可以强制其按照您想要的方式运行:使用命名函数表达式 A named function expression looks like a declaration but is not due to the function being declared as an expression. 命名函数表达式看起来像一个声明,但不是由于该函数被声明为表达式。

For example, in the following: 例如,在下面:

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

The value of f is bound at the declaration and will be immune to reassignment. f的值在声明中受约束,并且不受重新分配的影响。 In a named function expression, the function name is only defined inside the expression and therefore behaves more like a closure rather than a variable. 在命名函数表达式中,函数名称仅在表达式内部定义,因此其行为更像是闭包而不是变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM