- In [[Call]], we call the PrepareForOrdinaryCall to setup the callee environment
- In PrepareForOrdinaryCall, we create the FunctionEnvironment by calling NewFunctionEnvironment and use it as the callee's environment
- After that, we enter OrdinaryCallEvaluateBody, and it calls FunctionDeclarationInstantiation.
- Now in FunctionDeclarationInstantiation, reaching here, the current environment is the callee's environment created at the (2).
- FunctionDeclarationInstantiation step 11, we check
hasParameterExpressions. If there's default parameter values, it becomestrue. - At step 21, we create the mutable binding of the all parameters before executing any of parameter assignments. So all the variables in the upper scope that name is the same to the parameters are hidden now.
- After that, at step 24 and 25, we initialize (assign) parameter values to the created mutable bindings. Reaching here, the current environment is the callee's environment.
- Evaluate the default parameters within the callee's environment. The callee's environment has the mutable bindings to the all parameters.
So when the given JS code is the following,
{
var x = 20;
function foo(x = function() { return x })
{
print(x());
}
foo()
}The x inside the closure in the default parameter indicates the closure itself.
So I think print(x()) will print the closure function itself.