Originally published here
At the most basic level, the call stack is a data structure that utilizes the Last in, First out(LIFO) principle to store and manage function invocations.
Because there is only one call stack, function execution is done one at a time from top to bottom, making the call stack synchronous. In managing and storing function invocations, the call stack follows the Last in, First Out principle(LIFO) and this entails that the last function execution that gets pushed into the call stack is always the one to be cleared off, the moment the call stack is popped.
Global Execution Context. Initially, this Execution Context will consist of two things - a global object and a variable called
local execution context. So for each function execution, a new execution context is created.
- The thread of execution
- A local memory
Now, the moment a function is executed, a new
To further illustrate how this works, let's take a look at the piece of code below, I would work us through how it is executed.
global execution contextgets created and pushed into the
randomFunction, the function is merely defined but not executed at this time.
let generatedFunc = randomFunction()and since it hasn't executed the function
generatedFuncwould equate to
randomFunc()is created and it gets pushed into the call stack, taking the top position and pushing the global execution context, which we would call
randomFunc(), it begins to run the codes it finds within.
multiplyBy2, and since the function
multiplyBy2isn't executed yet, it would move to the return statement.
In the statement,
return multiplyBy2, it would be good to note that, what is returned isn't the label
multiplyBy2 but the value of
multiplyBy2. So when we return, what gets returned is the function definition and this gets assigned to the variable
generatedFunc what we have below:
multiplyBy2 and this time, assign it to the variable or label
In the next line,
let result = generatedFunc(2), we execute the function definition which
generatedFunc refers to (previously our
multiplyBy2), then this happens:
- The variable result is equated to
undefinedsince at this time the function it references hasn't been executed.
local execution contextwe would call
generatedFunc(). When a local execution context is created, it comes with it a local memory.
- In the local memory, we would assign the argument
2to the parameter
- Let's not forget that the local execution context
num * 2, and since
2stored initially in local memory, it evaluates the expression
2*2and returns it.
- In returning the evaluation of the expression
generatedFuncfunction, the returned value gets stored in the variable
resultthen the call stack gets popped, removing the
generatedFunc()context and getting the thread back to the
global()context. So when we
console.log(result), we get