I used to wonder how a programming language works behind the scenes and in particular javascript. After going through lot of resources i found most of them do not explain this part which i feel is very crucial to be a great developer. A big shout out to Namaste javascript series by Akshay saini on youtube. This article is majorly derived from what i learnt from those videos in simplified form. So lets get started.
some of the properties of javascript
javascript is a high level language:
A high-level programming language is more user-friendly and closer to humans in contrast to low level language. It is also independent of platform but it needs to be converted into machine language using an interepreter or compiler. *
javascript is a loosely typed or Dynamically typed language:
A loosely typed language explicitly does not require what data type to be mentioned. It does it behind the scenes and also the data types can be changed at runtime.
javascript is a synchronous single threaded language:
single-threaded means it can only execute one line of code at a time. synchronous means every other thing is put on hold until it is finished executing the current line of code.
what is Javascript Runtime environment
There are multiple things goes behind the scenes to execute the javascript code. All the things that are needed to run the javascript code is known as javascript runtime environment. Let's see what it contains.
- call stack:
This is where code is executed in the order of stack. This is where execution context is created. once the execution is finished it is popped off from the stack and it continues till the stack is emptied.
- event loop:
This is a looping algorithm that constantly checks if the call stack is empty or not. If it finds the call stack empty then it pushes the tasks from the call back queue and micro task queue into the call stack.
- callback queue:
Asynchronous programs like call back functions , web API calls such as setTimeout(), and setInterval() are pushed into the callback queue which are then pushed into the call stack by the event loop.
- micro task queue:
Microtask Queue gets the callback functions from Promises and Mutation Observer. The main difference between callback queue and micro task queue is micro task queue has higher priority means the tasks in micro task queue are pushed into the call stack before the callback queue tasks.
workflow of javascript run time environment
lets take the below example and see step by step
1. var n = 5
2. function square(num){
3. var ans = num * num
4. return ans
5. }
6. setTimeout(function hello(){
7. console.log("helloworld")},3000)
8. var square1 = square(n)
9. var square2 = square(4)
Execution context
eveything in javascript is executed in the form of execution context. As soon as the page loads a global execution context is created which is any code outside a function or you can say gloabl scope code and pushed into the call stack. An execution context contains two phases.
memory creation phase:
Before executing the code, javascript goes through the code and creates the memory for all the variables,functions and all other things. This is also called as hoisting.
The variables are stored with a value known as "undefined" and functions are stored with the whole exact code. After the memory creation phase then the code execution starts.
code execution phase:
code is executed one line at a time
line one is executed and n value is now 5.
line 2,3,4,5 is nothing but function statement.
At line 6 it encounters a setTimeout() which is a web api. The web api evironment takes the callback hello() and attaches a timer to it. once the timer expires it is pushed into the callback queue.
At line 8 it encounters a function call with square(n).Now again an exectution context is created for function call square and pushed into the call stack. It will also have memory creation phase and code execution phase.
Then the code execution inside the function starts. It return the value 25 and comes to the end of the code inside the function. Then this execution context is removed from the call stack and the control is moved to the global execution context. Value of square1 becomes 25.
similarly line 7 is also executed in the same way.
once it reaches the end of the program global execution context is also removed from the call stack and now it is finished.
All this while event loop will be checking if the call stack is empty and are there any tasks waiting in the callback queue and micro task queue. Now the call stack is empty and there is a task waiting in the callback queue. It pushes it into the call stack and the execution context is created for this callback.
Again it follows the same cycle with memory creation phase and code execution phase.
Then it logs "helloworld" to the console and it is removed from the call stack.