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.