Initially, the f(y)
function essentially invokes y
on itself. When you call f(y)
, it generates a fresh function that, upon execution, will perform x(y)
and yield the output.
To clarify, just substitute f(f)
for each f()
that you execute in this instance, considering that x === y
and y === f
. The reason i
seems to remain stagnant is because each execution produces a new i
.
Below the surface, the following actions take place:
f(f)()();
// equates to
const f1 = f(f);
const f2 = f1();
const f3 = f2();
// initial execution of f(f) occurs first, yielding () => {
// console.log(++i);
// return x(y); // essentially returning f(f) in this scenario
// }
Observe that running f(f)
results in x(y)
, where x(y)
appears to be identical to f(f)
. Though they look similar in code, they are distinct instances. Furthermore, i
does not transfer to this new function, nor does it carry over to other instances. Each f(f)
generates a fresh i
, without passing it on to subsequent functions.