Course contents
- 01Variables
- 02Primitive Data Types
- 03Operators
- 04Conditionals
- 05Arrays
- 06Array methods and properties
- 07Objects
- 08Functions
- 09Callbacks
- 10Arrow functions
- 11Promises
- 12Async and await
- 13Loops
- 14DOM Manipulation
- 15Syntax parser
- 16Execution context and hoisting
- 17Call stack
- 18WebAPI and setTimeout
- 19Closures
- 20Function Constructors and Prototypes
- 21By value vs by reference
Execution context and hoisting
The syntax parser wraps the executable code into an execution context. The execution context is an abstract concept of the environment in which code is being run: it’s either the default global environment (the code isn’t inside a function), or a function environment (the code is inside a function). The base execution context is the global execution context, that what’s accessible to everything everywhere in your code and in which the execution starts when the file first loads in the browser. For example:

While the parser was going through this code, it stored the variable “name” in the global memory. This way, we even have access to the value of the variable “name” within function “greeting”. However, the variable “age” was stored in local memory: it was declared within a function. If we wanted to use “age” outside of the “greeting” function, it wouldn’t be able to find any reference to a variable called “age”, as we called console.log in the global execution context, thus it would only look in global memory. We never declared a variable within our global execution context called “age”, hence the reference error that gets thrown: it can’t find a reference to variable called “age” in global memory, and it can NOT access the variable we defined within the function “greeting” as it only got stored in local memory, not global memory. However, anything that’s stored in global memory can be accessed in any local execution context.

The green arrow shows it’s possible to access anything stored in the global memory within a local execution context. However, it’s not possible to access anything declared within a local execution context, in the global execution context.
The JavaScript engine creates the execution context in two parts, the creation phase, and the execution phase.
Creation phase
The creation phase starts after the JavaScript engine has called a function, but hasn’t executed it yet. It simply scans the code that it’s going to execute later, and sets everything up for execution. During this phase, three things happen:
Memory space is set up. In the activation object, JavaScript stores the passed arguments, variables defined within that function, and the “arguments” object for this function.
Scope chain is created. As we should have access to the variables that were defined outside the function too, for example on the global object, the scope chain is created. This is a list of all available variables within that function.
Value of the “this” keyword is determined.
An important part of the creation phase is hoisting. What hoisting is get clearly visible when you compare the following two examples:

During the creation phase, memory space is set up where the variables are stored. This is called hoisting. Before your code gets executed, the JavaScript engine already has all the variables and functions in its memory, which is why you can call them. However, variables are stored with the default value of undefined, until you actually define them in your code. This is why you get the value of undefined returned if you use a variable in your code before defining it. Undefined does not mean not defined!
Not defined: I don’t have it in memory, meaning you haven’t ever declared it in your code.
Undefined: I have it in memory, I see you have declared it somewhere in your code, but you haven’t defined the variable in your code yet before the line on which you’re trying to access it.
eFunctions, however, are always hoisted entirely. This means that we can always call a function, even before the line where we actually write the function.

Now, here you might start to see the difference between arrow functions and regular functions too. With arrow functions, we actually declare a variable. This means that this variable will be stored in memory with the default value of undefined, until we actually define the variable in our code during the execution phase!

Execution phase
During the execution phase, JavaScript runs the code line by line. It interprets the JavaScript code, converts it to something the computer understands, compiles that code, then executes that code.
During this phase, the variable object is being updated. The values of the variables are no longer the default “undefined” in memory: after the interpreter interprets the line on which we define the variable, that value will be accessible in memory.

References and further reading
- MDN: HoistingWhy declarations appear to move to the top.
- MDN: thisHow the execution context decides this.