JavaScript Engine
JavaScript engines are inbuilt in all the modern browsers today. When the JavaScript file is loaded in the browser, the JavaScript engine will execute each line of the file from top to bottom (to simplify the explanation we are avoiding hoisting in JS). JavaScript engine will parse the code line by line, convert it into machine code and then execute it. Some of the well-known JS engines are listed below:
Browser engines
JavaScript engine consists of two components:
- Execution context stack
- Heap
Execution context stack (ECS)
Execution context stack is a stack data structure which follows the Last In First Out (LIFO) principle (the last item to enter the stack will be the first item to be removed from the stack). ECS stores the execution context for each function. Execution context is defined as an object which stores local variables, functions and objects. Primitive values like int, bool etc are stored inside the execution context object while function definitions and objects are not stored inside the execution context object, they are stored inside the heap. Execution context object just has the reference or memory address of where these function definitions and objects are stored.
JavaScript engine always executes the function which is at the top of the execution context stack.
By default, at the bottom of the ECS, we have a global execution context which deals with all the code in the global scope. Each function has its own execution context called functional execution context which gets inserted on the top of ECS as and when the function is called in the code. If the same function is called twice like in recursion, it will have two different functional execution contexts in the ECS.
When the execution of the function is completed, the JS engine itself removes it from the ECS and starts executing the function on the top of the stack.
As JavaScript engine has only one ECS, it can execute only one thing at a time which is at the top of the ECS. This is what makes JavaScript single threaded.
Heap
Heap is a large unstructured data structure which stores all the dynamic data like function definitions, objects, arrays etc. Execution context stack just contains their reference or in other words stores their memory addresses where these function definitions, objects and arrays are stored. The memory occupied in the heap continues to exist even after the JavaScript code execution has completed. They are removed by the JavaScript Garbage Collector.
JavaScript Runtime Environment (JRE)
So far we have discussed the JavaScript engine, but the JavaScript engine doesn’t run in isolation. It runs inside an environment called JavaScript Runtime Environment along with many other components. JRE is responsible for making JavaScript asynchronous. It is the reason JavaScript is able to add event listeners and make HTTP requests asynchronously.
JRE is just like a container which consists of the following components:
- JS Engine
- Web API
- Callback Queue or message queue
- Event Table
- Event loop
JavaScript Runtime Environment
We’ve already learnt about the JavaScript Engine. Let’s get to the other components in the list:
Web API
Web APIs are not part of the JS engine but they are part of the JavaScript Runtime Environment which is provided by the browser. JavaScript just provides us with a mechanism to access these API’s. As Web APIs are browser specific, they may vary from browser to browser. There may be cases where some Web APIs may be present in one browser but not in another.
Event Table
It is a table data structure to store the asynchronous methods which need to be executed when some event occurs.
Callback Queue or Message Queue or Event Queue
Callback Queue or Message Queue is a queue data structure which follows the First In First Out principle (items to be inserted first in the queue will be removed from the queue first). It stores all the messages which are moved from the event table to the event queue. Each message has an associated function. Callback queue maintains the order in which the message or methods were added in the queue.
Web API callbacks are moved from the event table to the event queue when an event occurs. For example, when AJAX calls are completed and the response is returned, it is moved from the event table to the event queue. Similarly, when the setTimeout method waiting time becomes zero it is moved from the event queue to the event table.
Event Loop
Methods are executed neither in the event table nor in the event queue. They are executed by the JavaScript engine, only if it is present in the ECS. So, for the execution of any method, we need to move that method from the callback queue to the execution context stack. This is what the event loop does! Event loop continuously checks if the execution context stack is empty and if there are any messages in the event queue. It will move the method from the callback queue to ECS only when the execution context stack is empty.
We will understand all the above concepts with the help of setTimeout function so, let’s see what is setTimeout
setTimeout
setTimeout and setInterval are called as timer functions in JavaScript. They are used to schedule the execution of functions. They are not provided by the JS engine itself but they are provided by the browser as part of the window object.
Conclusion
In this article, we studied components of the JavaScript engine and run-time environment. On the basis of working of all the components, we understood the working of setTimeout function.