JavaScript: Understanding Under The Hood Of a Browser

Eduard Hayrapetyan
Preezma Software Development Company
7 min readJul 12, 2020

Overview

This article is about deepening our knowledge of JS by understanding how our code gets executed. If you are new to JavaScript šŸ‘¶, then this article will help to learn how JavaScript works. If you are an experienced šŸ‘“, JavaScript developer hopefully, this will be a good refresher for you.

Understanding the browser environment, what it is composed of and how it works will make you more confident in writing JavaScript and well-prepared for potential issues that might happen.

The JavaScript Engine

Basically, the engine is a program that translates your JavaScript into machine code and executes the result on a computerā€™s central processing unit (CPU). A popular example of a JavaScript engine is Googleā€™s V8 engine.The V8 engine is used inside Google Chrome, Node.js ,electron and among others.And there are various JavaScript Engines that are available for use. You can refer this Wikipedia page for the list of available JS engines.

V8 Does:

  1. Compiles and executes JS code
  2. Handling call stack ā€” running your JS functions in some order
  3. Managing memory allocation for objects ā€” the memory heap
  4. Garbage collection ā€” of objects which are no longer in use
  5. Provide all the data types, operators, objects and functions

V8 Can:

  1. Provide the event loop, but this is sometimes implemented by the browser as well.

V8 Doesnā€™t:

Know anything about the Web APIs like DOM elements and events, XMLHttpRequest, fetch, setTimeout, setInterval and so on, which are accessible via JavaScript.

This is a very simplified view of what it looks like:

The mechanism consists of two main components:

  • Memory Heap ā€” is an unstructured memory that is used for memory allocation of the variables and the objects.
  • Call Stack ā€” is a LIFO data structure that is used for function calls that record where we are in the program.

šŸ„ž Call Stack

JavaScript is a single-threaded programming language with a single call stack. It means that your code is executed synchronously, we only have a single call stack, in other words, we can only execute one thing at a time.

If we execute a function, V8 pushes frame on top of the stack. When we return from a function, V8 pops off the frame. Letā€™s take an example.

Following is the sequence of steps when JavaScript executes the code:

  1. Start execution using the main thread referred to as main() here.
  2. Identify the function which needs to executed and add it in the call stack.
  3. Identify other function which the current function executes and add it in the call stack.
  4. Upon completion of the function remove its reference from the call stack.
  5. Repeat steps #2 to #4 till the code finishes execution.
  6. After all the code has finished execution, remove main() from the call stack.

Hence, if any other program want to execute something, it has to wait until previous program is completely executed. This means that while a function is being executed, the engine cannot run another context at the same time. It also means that every time a function is pushed onto the call-stack, it then becomes the active executing context and takes control flow away from whatever function called it, until it returns either explicitly (with a return statement) or implicitly (when all instructions have been executed).

So letā€™s think of one scenario. What if a browser sends a HTTP request to load some data over network or to load an image to display on web page. Will browser freeze until that request is resolved? So how then do we achieve asynchronous JavaScript with itā€™s illusion of multiple things happening all at once?

Browser comes with a JavaScript engine which provides JavaScript runtime environment and uses more than just a JavaScript engine. This is what browser under the hood looks like.

The big picture šŸ§

JavaScript runtime actually consist of 2 more components event loop and callback queue. Callback queue is also called as message queue or task queue.

Apart from JavaScript engine, browser contains different applications which can do variety of things like send HTTP requests, listen to DOM events, delay execution using setTimeout or setInterval, caching, database storage and much more. These features of browser help us create rich web applications.

But think about this, if browser had to use same JavaScript thread for execution of these feature, then user experience would have been horrible. Because even when user is just scrolling the web page, there are many things going on, in the background. Hence, browser uses low level language like C++ to perform these operations and provide clean JavaScript API to work with. These APIs are known as Web APIs.

These Web APIs are asynchronous. That means, you can instruct these APIs to do something in background and return data once done, meanwhile we can continue further execution of JavaScript code. While instructing these APIs to do something in background, we have to provide a callback function. Responsibility of callback function is to execute some JavaScript once Web API is done with itā€™s work. Letā€™s understand how all pieces work together.

So when you call a function, it gets pushed to the stack. If that function contains Web API call, JavaScript will delegate control of it to the Web API with a callback function and move to the next lines until function returns something. Once function hits return statement, that function is popped from the stack and move to the next stack entry. Meanwhile, Web API is doing itā€™s job in the background and remembers what callback function is associated with that job. Once job is done, Web API binds result of that job to callback function and publishes a message to callback queue with that callback. The only job of event loop is to look at callback queue and once there is something pending in callback queue, push that callback to the stack. Event loop pushes one callback function at a time, to the stack, once the stack is empty. Later, stack will execute callback function.

Letā€™s see how everything works step by step using setTimeout Web API. setTimeout Web API is mainly used to execute something after few seconds. This execution happens once all code in the program is done executing (when stack is empty).

Hereā€™s a visualization of how it all works from Philip Robertsā€™ speech from JSConf EU 2014

What I think should be noted is the way setTimeout actually works. Calling setTimeout(function cb(){...}, 5000) doesn't mean foo will be executed in precisely 5 seconds; it means that in 5 seconds cb will be put into the callback queue, where it will wait until the stack is empty. This is why sometimes setTimeout(..., 0) is used: instead of just executing its callback immediately, it waits until all the other stuff is done.

Thereā€™s a resource called Loupe (also created by Philip Roberts) that visualizes JavaScript code and shows how the stack, the WebAPIs, the callback queue and the event loop interact with each other.

Heap

Sometimes V8 doesnā€™t know at compile time how much memory an object variable will need. All the memory allocation for such data happens in the heap ā€” unstructured region of memory. Objects on the heap live on after we exit the function that allocated the memory.

V8 has a built-in Garbage Collector (GC). Garbage collection is a form of memory management. Itā€™s like a collector which attempts to release the memory occupied by objects that are no longer being used.

You can investigate heap by making a snapshot in Chrome Dev Tools.

Devtools āž”ļø Memory ā¬‡ļø Take snapshot

Since we donā€™t have access to infinite amount of memory, there is comes V8 built-in Garbage Collector (GC). Garbage collectorā€™s job is to go through objects that are allocated in memory and determine whether they are dead or alive. Those that are alive get to stay in memory, those that are dead get removed, and memory gets allocated back to the heap.

Conclusion

Thanks for reading! I hope that after reading this article you have a better understanding of the mechanics behind JavaScript. These concepts also act as a building block for a greater understanding of other concepts such as scopes and closures. Please, click the clap šŸ‘, if the article above was helpful for you.

--

--