How JavaScript Works?
So you are into JS, and have been wondering how JS works? Well, you are at the right place. Welcome aboard!
This post was originally shared here
JavaScript is a 'synchronous single-threaded' language
You have read this somewhere, and what does this mean? Just go on reading, and you will learn it along the way.
I started coding, building small projects, and I used to think- what happens when I run a code? How JS works? What magic happens in the background?
Today, let's understand how js works. I will give a simple explanation from my limited knowledge.
Say you coded a small program - declared variables, created fn, etc., and you run it via your browser. So how does the browser knows JS? How can it run your code?
Well, the good thing is that every major browser has its own JS engine.
Why do they have a JS engine?
Most of the websites are using JS in some way, and the browser needs to interact with, and run JS efficiently in the webpage. Hence, the JS engine.
Okay, which JS engine do the browsers use? Most browsers have developed their own JS engine. Chrome uses V8 engine built by Google, Firefox has Spidermonkey, Safari has Nitro etc.
Now you know why some browsers do the job well and others not.
Now that said, let's get back to running our code.
Say we have a small code:
var a = 2;
var b = 4;
function add() {
var ans = a + b;
return ans;
}
add();
When we run this, an Execution Context(Global Context) is created by JS as the first step before executing the code. Think of this as a big box. This is where everything in JS happens.
Now this Execution Context is passed to what is called a Call Stack - where the main execution happens. Remember this. Think of Call Stack as a table where we keep files on top of another.
Now we know a Global Context is created when we run the code, and this Global Context is passed to a Call Stack for execution.
Now let's see what happens inside the Global Context.
The Global Context is created in two phases:
1) Memory Component - this is where all the variables and functions are stored as
key : value
pair. Key can be variable and value is its current value.
Here in the first phase, variable 'a' will be stored as 'undefined'. This is stored in the Memory Component as a : undefined
Here the values for these variables are not assigned by the Memory component. This happens in the next phase. For now, variables are assigned as undefined
and for functions, the whole function itself is added.
2) Code Component - this is where the execution of each line of code happens. In this phase, the values are assigned to the variables.
Now the value of a
becomes 2
from undefined
and will be stored as- a : 2
JS executes the code one line at a time. JS can't do tasks more than one at a time. So here it is, this is what single-threaded means.
JS executes code in a specific order. The first line is executed and only when this is finished it goes for the next line. It cannot jump to the 3rd line before executing the 2nd line. This is known as synchronous.
So there you go - 'synchronous single-threaded'.
Now when it meets a function, a new Execution Context like the first one is created inside the first Execution Context, with the same two phases, and the procedure is the same.
Now at the same moment, this new Execution Context is passed to our Call Stack. That is a new box is kept on top of another box that is on the table.
Now our Call Stack has the first Execution Context at the bottom and on top of it, this new Execution Context is passed. JS tries to quickly execute whatever comes to the Call Stack without waiting for anything. After the execution, this new Execution Context is deleted and it is also popped out from Call Stack. This happens every time a function is met inside the code.
Now after functions are done, it moves to the next line, and finally, the first Global Execution Context is also deleted and popped out from the Call stack. Hence the Call Stack also gets empty.
Okay, let's look at this: What would have happened if there were two functions in the Global Execution Context? Yes, you guessed it right.
Two new Execution Contexts will be created and does the same thing as explained above. But remember, it doesn't form the two new Execution Context together, but first completes the first function and it is deleted. And only then it goes to the next function.
Simple right?
Now think about this. What if there is a function inside a function? I guess you got this too.
In this case, there will be 3 Execution Contexts, and also these 3 will be passed to Call Stack.
The Execution Context of the third function will be on the top of the Call Stack followed by the other two on the bottom.
That is, picture it this way, on the bottom of the Call Stack is our Global Execution Context, and on top of this is the main function, and the third will be the function inside this main function.
And then after execution, each of them will be deleted one by one, the top Execution Context is executed first and then is deleted from the Call Stack, then the next one is executed and deleted from the Call Stack, and this is repeated until the Call Stack becomes empty.
This is how code inside JS works. I have tried to explain this in the best possible way.
Thank you for reading!
Let's connect on twitter