Understanding the JavaScript runtime environment

What‘s going on “under the covers” of JavaScript and the runtime environment

Gemma Croad
5 min readAug 2, 2020
A diagram that helps visualise the JavaScript runtime environment

Most developers may have heard of the call stack, or the V8 Engine, or might be aware that JavaScript is a single-threaded language when it’s using a callback queue. With so much of what is going on in the browser being dependent on JavaScript, how many people really know what is going on “under the covers”? Are we making the best of everything the language and environment have to offer? Do we have a deep enough understanding of the internals to help us to build great software and delight our users?

What is the runtime environment?

The JavaScript runtime environment provides access to built-in libraries and objects that are available to a program so that it can interact with the outside world and make the code work.

In the context of a browser this is comprised of the following elements:

  1. The JavaScript engine (which in turn is made up of the heap and the call stack)
  2. Web APIs
  3. The callback queue
  4. The event loop

It’s good to be mindful that the runtime environment can take on different forms based on the context, for example, the runtime environment in a browser is very different from that of Node.js. These differences are primarily at the implementation level, so most of the following concepts are still relevant.

The JavaScript engine

To start writing JavaScript we don’t need to install any specific software because each web browser has its own version of the JS engine that parses the code for us. Chrome uses the V8 JS engine which has been developed by the Chromium Project. Firefox uses SpiderMonkey which was first written by Brendan Eich at Netscape and is now maintained by the folks at Mozilla.

The purpose of the JavaScript engine is to translate source code that developers write into machine code that allows a computer to perform specific tasks.

For the purpose of this article, we are going to focus on the V8 JavaScript engine.

The heap

The heap, also called the ‘memory heap’, is a section of unstructured memory that is used for the allocation of objects and variables.

The call stack

The call stack is a data structure that keeps track of where we are in the program and runs in a last-in, first-out way. Each entry in the stack is called a stack frame. This means that the frame at the top of the stack is the one the engine is focused on, and it will not move on to the next function unless the function above it has been removed from the stack.

As the JS engine steps into a function, it is pushed onto the stack. When a function returns a value or gets sent to the Web APIs, it is popped off the stack. If a function doesn’t explicitly return a value then the engine will return undefined and also pop the function off the stack. This is what is meant by the term “JavaScript runs synchronously”; it is single-threaded, so can only do one thing at a time.

Web APIs

The Web APIs are not a part of the JavaScript engine, but they are part of the runtime environment provided by the browser. There are a large number of APIs available in modern browsers that allow us to a wide variety of things. Some of the most common categories of browser APIs let us:

  • Manipulate documents: One of the most common Web APIs used is the DOM API, which allows developers to manipulate HTML and CSS, letting us create, change and even remove HTML and dynamically apply styles to our web pages.
  • Draw and manipulate graphics: Widely supported in browsers, the Canvas API and the Web Graphics Library API let us programmatically update pixel data contained in a <canvas> element.
  • Fetch data from a server: The Fetch API provides an interface for fetching resources across the network by using generic definitions of the Request and Response objects.

Features like event listeners, timing functions and AJAX requests all sit in the Web APIs container until an action gets triggered. A request finishes receiving its data, a timer reaches its set time or a click happens and this triggers a callback function to be sent to the callback queue.

The callback queue

The callback queue stores the callback functions sent from the Web APIs in the order in which they were added. This queue is a data structure that runs first in, first out. The queue uses the array push method to add a new callback function to the end of the queue and the array shift method to remove the first item in the queue.

Callback functions will sit in the queue until the call stack is empty, they are then moved into the stack by the event loop.

The event loop

The job of the event loop is to constantly monitor the state of the call stack and the callback queue. If the stack is empty it will grab a callback from the callback queue and put it onto the call stack, scheduling it for execution.

This is why JavaScript often gets described as being able to run asynchronously, even though it is a single-threaded language. JavaScript can only execute one function at a time, so this means it is synchronous, but as we can push callbacks from the Web APIs to the callback queue and in turn, the event loop can constantly add those callback to the call stack, we think of JavaScript as being able to run asynchronously.

Summary

  • The runtime environment is what makes JavaScript code work, and in a browser in consists of the JS engine, a lot of Web APIs, a callback queue and the event loop
  • The JS engine translates source code into machine code that allows a computer to perform specific tasks at the hardware level
  • Web APIs extend the JS language and push callback functions to the callback queue once actions are complete and data has been received
  • The callback queue stores callback functions in order, ready to be executed
  • The event loop is constantly monitoring the call stack and the callback queue; if the call stack is empty it will move the callback function at the front of the queue to the call stack, scheduling it for execution

This article was inspired by a talk given by Phillip Roberts titled “What the heck is the event loop anyway?” at JSConf EU. It motivated me to go “poking around under the hood” to learn a little more about how JavaScript really works and I feel like this is going to make me a better developer in the long run.

--

--

Gemma Croad

Software Engineer, a11y and user advocate, experienced remote worker, creative coder, lover of all things front-end.