JavaScript Developer

What is JavaScript execution context

02 July, 2019

What is execution context in JavaScript? To make it simple, ask yourself which part of your code is currently executing. Execution context is simply the section of code that is currently running.
It can be the on the global context or inside a function context.

Whenever we run any script in JS, the global execution context will be the default context. Whenever a function is executed, that function will take over from global and become the current execution context until it finishes its task.

Every execution context will go through two phase:

  • creation phase.
  • execution phase.

Creation phase

During the initial creation phase the engine will do this step:

  1. setup the global object.
  2. sets up memory space for all functions and variable in the global scope.

Function declaration in the global scope will be activated and can be access straight away.

On the other hand, variables are different. Its value can only be access when the engine has gone through the second phase.

Here's an example:

function sing() {
    console.log('a song')
let title = "pretender"

The code above will run error-free even if we execute the function before declaring it because the function has been activated during the creation phase.

If we change a little bit and try to run this code below, we'll get an error because the variable has not been activated yet:

sing() // a song
console.log(title) // ReferenceError: title is not defined
function sing() {
    console.log('a song')
let title = "pretender" 

* there wont be an error if we use var instead of let or const. the value will instead be undefined

Execution phase

After the creation phase, the engine will start executing the code. It will go through the code line by line. During this phase, the engine will start assigning values to variable if it finds a line that contains variable initialization. After it goes through that line, that variable will be activated and is ready to be use. Example:

let event = "lollapalooza";
const venue = "wembley arena";
console.log(event) //lollapalooza
console.log(venue) //wembley arena

This rule also applies to function expression. In contrast with function declaration mentioned above, functions created using function expression isnt activated until the execution phase. Lets see an example:

jump()// ReferenceError: jump is not defined
const jump = function() {
    console.log('jump around')
jump() // jump around

Whenever the engine encounter a line of code where a function is being invoked, a new execution phase will be created for that function. The functions/variables inside that particular function will go through the creation phase and the execution phase. The engine will once again start to go through the code line by line. This will happen everytime a new function is being invoked.

let singer = 'stormzy'

function sing() {
    let song = "crown";

sing() // crown
console.log(singer) // stormzy

We start at the global execution context creation phase where the function is initialized. Then the engine starts executing. When it encounter sing() invocation, it creates a new execution context and start working with the code inside that function. After it finishes executing the code inside that function, the engine will go back to the previos execution context (global) to see if there's more code to be run. This will go on and on until there's no more code to be processed by the engine.

Lets explore another example:

function ready() {
    let wave = "hello"

function scream() {
    let word = "jump"

let word = "stop"

// the result in console:
// "jump"
// "hello"
// "stop"

Here we have two functions with different place of execution. Lets go step by step to see how execution works with this code:

  • First, we start at the global execution context.
  • When we invoke the function ready(), a new execution context is created.
  • Inside that function first things that happen is we invoked another function right away so the engine creates a new execution context for the function scream().
  • In the scream() function, we initialize the variable word and then runs the second line.
  • Engine then saw theres no more code to run. So it removes the current execution context and go back to previous context which is ready()
  • Inside ready(), we continue where we left off before. It will initialize the variable wave and runs the second line.
  • Then The ready() function finishes and the engine saw theres no more code to run, so it removes the execution context and return to the global execution context.
  • Engine continue to initialize the variable word in the global context and then runs the last line.

So that's basically how execution context works. This concept is important to understand because it strongly relates to the concept of scope and closure. It also makes us understand how the JS engine works behind the scene. When you understand this concept, you will easily grasp the concept of event loop. I highly recommend watching this awesome video on youtube to learn even more.