Perfection Kills Quiz (part 12)

Previous posts on Perfection Kills JavaScript quiz: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.

12)

(function f(){
  function f(){ return 1; }
  return f();
  function f(){ return 2; }
})();

Correct answer: 2.

For simplicity, I will refer to the "outer" function

function f(){
  function f(){ return 1; }
  return f();
  function f(){ return 2; }
}

as Function A,  to the function function f(){ return 1; } as Function B, and to the function function f(){ return 2; } as Function C.

Function A is immediately invoked. The snippet of code evaluates to the return value of this function. In order to determine this return value, we have to find out what f in the statement return f(); refers to.

Theoretically, f could refer to any of the three functions: A, B, or C. Let me start by explaining why f could have referred to any of them under some circumstances.

Function A is defined with a named function expression (you can read more on them here). The name of Function A f is available within the function local scope. Hence, f in the function body (specifically in the statement return f();) can refer to Function A.

Function B is defined with a function declaration. Function declarations 'move' function definitions to the top of the current scope. In case of Function B, this is not too interesting, because this function is declared at the top of the current scope anyway.

Function C is defined with a function declaration too. Although this function is declared at the very bottom of Function A body, its definition is 'moved' to the top of the current scope (in this case the current scope is the scope of Function A). Hence, the variable f in the statement return f(); can refer to Function C.

Obviously, when the statement return f(); is executed, the variable f refers to one value only. Let's find out which one.

First, when Function A has just been initialized, the identifier f points to Function A. As explained in the post on question 5 of Perfection Kills Quiz, the Function A's identifier f is an outer variable relative to the Function A local scope. Then the declaration of Function B creates a new variable f, which points to Function B and belongs to the Function A local scope. Finally, the declaration of Function C redefines f in the local scope and makes it point to Function C.

At the moment when the line return f(); runs, the interpreter will first look for a variable f in the Function A local scope and will find it there. This variable f points to Function C. The expression f() evaluates to 2, and Function A returns 2.

All posts on Perfection Kills JavaScript quiz: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.