so what I can infer is that the parent lexical environment is attached as soon as it encounters a function definition (the return function), is this correct ?
Attached to the newly created function object, yes.
the parent lexical environment is created when a function is declared and reached in the code and not when it is executed?
No. The parent environment already exists when function definition is evaluated. The parent environment is the environment that contains the function declaration.
In your example:
- Calling
makeAdder
creates environment A with x
set to 5
.
- The inner function (
function (y) {...}
) is created and gets a "reference" to A.
- The return value of
makeAdder
(the inner function) is assigned to add5
.
- Calling
add5
creates environment B with its parent is set to A. This is possible because the function got the reference to A when it was created.
x
is looked up in B. It's not found, so it's looked up in B's parent, A, where it is defined.
- ...
Please forgive me for the long text I just want to clarify when is the parent and local lexical environments are created.
There are different types of environments in ECMAScript, all created at different times:
- Declarative environment: Base of all other environments and created when evaluating a block.
- Function environment: created when a function call is evaluated.
- Global environment: created when a script is evaluated / when the runtime is initialized.
There are more, but these should be the most relevant ones for this question. For more info see https://www.ecma-international.org/ecma-262/8.0/index.html#sec-lexical-environments
However, at each given time, only one environment is "active" (top of the stack). Whenever a new environment is created, the currently active environment becomes its parent.
The spec defines and uses the following operations for creating new environments:
NewDeclarativeEnvironment ( E )
NewObjectEnvironment ( O, E )
NewFunctionEnvironment ( F, newTarget )
NewGlobalEnvironment ( G, thisValue )
NewModuleEnvironment ( E )
where E
is another environment (becoming the new environment's parent) and F
is a function object. NewFunctionEnvironment
gets the parent environment from the function object. NewGlobalEnvironment
doesn't accept a parent environment because a global environment cannot have any.
Note: Environment A also has a parent, the global environment (assuming the code is evaluated in global scope). The global environment doesn't have a parent.