First of all parser goes through each and every line of code and checks for any syntax errors. After parsing everything parser will create an abstract syntax tree(AST). This helps in representing the code in a much more structured way Let us see a sample AST for below code snippet.
An Execution context is basically the environment in which each line of code gets executed. It is created in 2 phases
- Memory Creation Phase — In this phase memory is allocated to all functions and variable without actually executing them. The JS engine runs through the code and will identify variable and functions which will be used in execution phase. All the variables will initially be set to undefined. Hoisting also takes place in this phase. We will look at hoisting bit later.
- Code execution phase — In this phase each line of code is executed. The variables are assigned to their respective values.
Here the function func1 and variable key are accessed before they are defined but because of hosting no error is thrown. The function gets executed completely but the variable key is printed as undefined. This happens because of the way in which hoisting takes place for variables and functions is different. The variables are initially set to undefined and in case of functions their whole code is picked into the memory. Lets see one more example of hoisting
There are 2 types of execution context:
- A this variable. In global execution context this variable equals the global window object.
This means that all variables that are declared outside of any functions will be attached to the window object and can be referenced by using this.
2. Function Execution context — Whenever a function is executed a separate execution context is created for each function. Any variable declared inside a function will be part of that respective functional context but not of global execution context.
This is a normal stack with LIFO(Last in first out) order and stores all the execution contexts that were created during code execution. Initially a global execution context is pushed into the stack.
Whenever a new function invocation is there a new execution context is created for that function and pushed to top of stack. The function whose execution context is at top of the stack is executed first and after execution ,its execution context is popped off from the stack and control goes to the context below it.
Let us see this with help of an example
The stack trace for above code will be like below:
Step 1 — Initially the global execution context will be pushed into the stack.
Step 2 — As soon as func1 is triggered a separate execution context is pushed into the stack.
Step 3 — Then func2 is triggered and new execution context is created for it.
Step 4 — After func2 is executed it gets popped of from the stack the control returns back to func1.
Step 5 — After func1 is executed it gets popped off from stack.