There are four kinds of context in which variable or function declarations would occur: Global, module, function, and block. This article focuses on the global context.
Steps in Specification of Declarations in Global Context
A JavaScript engine instance is responsible for the code execution. The engine will parse the code to identify what kinds of statements and expressions there are.
But before actually executing the code line by line, the engine needs to set up the environment that is essential for executing.
By design, all JavaScript code should run in its corresponding execution context in a single execution stack. So, the engine needs to create the first execution context and push it to the stack.
Here are the steps in the specification of how a piece of global code is processed before execution:
- The engine creates and initializes a
Realm
for the execution context: (InitializeHostDefinedRealm)- Create
[[Intrinsics]]
= new Record- Set properties of
realmRec.[[Intrinsics]]
for engine internal use.(%Object%, %Function%, %Array%, %String%, %Number%, %Map%, %Set%, %Date%…)
- Set properties of
- Create
[[GlobalObject]]
=undefined
- Create
[[GlobalEnv]]
=undefiend
- Create an empty
global
object and set it torealmRec.[[GlobalObject]]
globalEnv
← a new Lexical Environment with:- outer environment ←
null
- EnvironmentRecord ← Create a global environment record with:
[[ObjectRecord]]
← Create a object Environment Record withglobal
as its binging object[[GlobalThisValue]]
← theglobal
object[[DeclarativeRecord]]
← Create a declarative Environment Record without bindings[[VarNames]]
← Create a new empty List
- outer environment ←
- Create an empty
- Set all properties (global object, functions…) to
realmRec.[[GlobalObject]]
- Create
- The engine sets the first execution context (ScriptEvaluation)
scriptContext
← a new ECMAScript code execution context with:Function
←null
Realm
←scriptRecord.[[Realm]]
ScriptOrModule
←scriptRecord
VariableEnvironment
←scriptRecord.[[Realm]].[[GlobalEnv]]
LexicalEnvironment
←scriptRecord.[[Realm]].[[GlobalEnv]]
- The engine instantiates the global declarations (GlobalDeclarationInstantiation)
envRec
= environment record ofscriptRecord.[[Realm]].[[GlobalEnv]]
- Get
LexicallyDeclaredNames
andVarDeclaredNames
(function + var) from script - Conflict Checks
- for Lexical Declarations
- for Variable Declarations (only conflict with lexical not allowed)
- Split
VarScopedDeclarations
- Pick Function Declarations: If there’re duplicated functions with same name, only take the last
- Pick Variable Declarations: If there’re duplicated variables with same name, only take the first
- Instantiate Lexical Declarations
- const →
envRec.CreateImmutableBinding(name)
, let →envRec.CreateMutableBinding(name)
- Note: Lexically declared names are only instantiated here but not initialized
[[DeclarativeRecord]].CreateMutableBinding(name)
and[[DeclarativeRecord]].CreateImmutableBinding(name)
- const →
- Instantiate and initialize Function Declarations
envRec.CreateGlobalFunctionBinding(name, InstantiateFunctionObject, false)
- Create and initialize a global function binding in the
[[ObjectRecord]]
component of a global Environment Record.
- Create and initialize a global function binding in the
- Instantiate and initialize Var Declarations with
undefined
envRec.CreateGlobalVarBinding(name, false)
- Used to create and initialize to
undefined
a global var binding in the[[ObjectRecord]]
component of a global Environment Record.
- Used to create and initialize to
- The engine executes the code
- Evaluate the assignments of values to
var
,let
, andconst
variables when encountering these statements.
- Evaluate the assignments of values to
We can see the behavior known as “hoisting” in these steps:
- Lexical declarations are only instantiated here but not initialized.
- Function declarations are instantiated and initialized with the function object as its value
- Var declarations are instantiated and initialized with
undefined
as its value
Recap
Here is the outline of the steps to prepare a new execution context for a global code execution:
- Create and initialize a
Realm
record with its[[Intrinsics]]
,[[GlobalObject]]
, and[[GlobalEnv]]
. The environment record of[[GlobalEnv]]
has some important internal slots:[[ObjectRecord]]
[[DeclarativeRecord]]
[[GlobalThisValue]]
← point to the[[GlobalObject]]
object
- Create first ECMAScript code execution context with
Realm
, and its[[GlobalEnv]]
forVariableEnvironment
andLexicalEnvironment
- Instantiate the declarations in the
scriptRecord
to the environment record ofscriptRecord.[[Realm]].[[GlobalEnv]]
- lexical → bond to
[[DeclarativeRecord]]
, not initialized - var → bond to
[[ObjectRecord]]
, initialized withundefined
as its value - function → bond to
[[ObjectRecord]]
, initialized with the function object as its value
- lexical → bond to
- Finally the engine can start executing the code and evaluating the assignments.