0

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. However if you call g it will still alert the first argument. What's happening? Shouldn't calling g result in a stack overflow?

What I understand is that inside the function f (now g) the variable f is no longer bound to f. It becomes a free variable. Hence inside f the variable f now points to 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.

3
  • When I run var g = f, f = alert; g() it throws a TypeError (undefined is not a function) as I expected (because g is assigned the value of f while f is undefined). How are you guys ending up with g as alert? Or is that second block supposed to be run in the same context as the first? Commented Jan 6, 2014 at 2:45
  • That's not what the OP is doing, he's doing: var f = function () {...}, g = f, f = alert; g(); Commented Jan 6, 2014 at 2:49
  • Ah, ok, I thought they were two separate examples. You're right then, no recursion because f is reassigned Commented Jan 6, 2014 at 2:50

2 Answers 2

4

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. Looks like it's working as designed.

Sign up to request clarification or add additional context in comments.

Comments

1

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. 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. 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.