JavaScript Garbage

JavaScript offers an effective garbage collection mechanism for memory handling. The process of memory management in JavaScript is automated and operates behind the scenes. Each time we generate new objects, functions, primitives, and variables, these components consume memory. The question arises: How does JavaScript handle and remove these elements?

In this section, we will discuss all the internal processes of memory management in JavaScript. We will focus on the following topics:

  • Memory life cycle in JavaScript
  • Memory Allocation in JavaScript
  • Releasing of a Memory When It is not in use
  • JavaScript Garbage Collection
  • References Concept in JavaScript Garbage Collection
  • Mark-and-sweep algorithm

In contrast to languages like C, which utilize manual memory management techniques like malloc and free, JavaScript handles memory allocation and deallocation automatically for new objects. This automatic memory management system contributes to JavaScript being recognized as one of the most efficient programming languages for web development.

To delve deeper into JavaScript Garbage collection, it is essential to comprehend memory management in JavaScript.

Memory life cycle

The memory life cycle for every programming language is pretty much similar. It works in the following manner:

  • It allocates the required memory for the new instance
  • Use the allocated memory (read, write) whenever an instance is invoked
  • Finally, releases the allocated memory when it is not in use anymore.

However, the implementation of the second part can vary across programming languages based on their design and application. While steps one and three are clearly defined in low-level languages like C, they are often implicit in high-level languages such as JavaScript.

Memory Allocation in JavaScript

Value initialisation

In JavaScript, memory allocation for declared values occurs automatically. There is no requirement to manually assign memory for variables and objects that are created.

Let's examine the example below, which illustrates the allocation of memory for various kinds of variables and objects:

Example

const a = 200; // It will allocate the memory for a number type variable

const a = 'anystring'; // it will allocate the memory for a string type variable



const new_obj = {

  a: 5,

  b: null,

}; // It will allocate the memory for an object and contain values



// Just like the objects, it will also allocate memory for the array and

// contained values

const my_array = [5, null, 'anystring'];

// JavaScript also allocated memory to a function

function my_function(a) {

  return a + 5;

} // It will allocate a function (which is a callable object)

// JavaScript also allocates memory to a function expressions object

anyHtmlElement.addEventListener('click', function() {

  htmlElement.style.backgroundColor = 'green';

}, true);

In the example provided, it is evident that JavaScript assigns values to individual objects, variables, and methods.

Function Calls

When using JavaScript, certain function invocations can result in the allocation of objects. For instance, when we instantiate a date object using the Date function, memory will be allocated for the newly created Date object. An illustration of this concept is provided below:

Example

const d = new Date(); // it will allocate the memory for a Date object

const e = document.createElement('div'); // It will allocate the memory for a DOM element

Certain functions consume memory in JavaScript as well.

Example

const s1 = 'mystring';

const s2 = s1.substr(0, 2); // s2 is a new string

//In JavaScript, strings are immutable values

// In the case of a string, JavaScript may decide not to allocate memory,

// but it will store the range value, which is [0, 3].

const my_array1 = ['string1 string', 'nan nan'];

const my_array2 = ['newstring', 'nan nan'];

const my_array3 = my_array1.concat(my_array2);

// new array with 4 elements being

// the concatenation of my_array1 and my_array2 elements.

Reading and Writing Values

When values are utilized in JavaScript, they are accessed in the allocated memory for both reading and writing operations. These values can be read from and written to the allocated memory of a variable, an object property, or can even be passed as an argument to a function.

Releasing of a Memory When It is not in use

Releasing allocated memory is a critical phase where many memory management challenges arise. The key challenge here is identifying the point at which a particular variable, object, or function is no longer required.

Developers using low-level programming languages are required to explicitly indicate when they intend to free up the memory of a created object.

However, high-level programming languages such as JavaScript employ a mechanism called garbage collection to handle memory automatically.

The primary purpose of garbage collection is to automatically track and identify instances where a particular block of memory is no longer needed and then retrieve it.

The process of memory management relies entirely on estimation, making it challenging to definitively ascertain the necessity of a particular memory segment. This determination is considered undecidable. This is where the JavaScript garbage collector plays a crucial role by effectively handling memory management.

Having covered the topic of memory management in JavaScript, let's now shift our focus to the core subject of Garbage Collection:

JavaScript Garbage Collection

The primary challenge encountered by the garbage collector involves determining whether a particular memory will be used or not through automatic means. In this situation, the garbage collector enforces a constraint to address this issue. JavaScript tackles this problem by employing the notion of references. Let's delve into the understanding of what references entail:

References Concept in JavaScript Garbage Collection

JavaScript's automatic memory management is based on the idea of references. In memory management, one object is considered a reference to another object if the latter is accessed at a later point in the program, whether that access is implicit or explicit. For example, an object will have a reference to its prototype, which is an implicit reference, and to the values of its properties, which are explicit references.

In this situation, the concept of an object will be expanded beyond typical objects in JavaScript to include its scope.

Reference-counting garbage collection

The JavaScript garbage collection process is guided by an algorithm that tracks references. This algorithm assesses whether an object requires evaluation to establish if other objects are still referencing it. An object is marked as garbage when it no longer has any references pointing to it.

Let's understand it with the below example:

Example

let a = {

  x: {

    y: 5

  }

};

// Here, two objects are created; x and y. where x is referenced by the other y as one of its properties.

// The other is referenced by virtue of being assigned to the 'a variable.

// Here, none of the given objects can be garbage-collected.



let a = b;      // The 'b' variable is the second thing that has a reference to the object.



a = 5;          // Here, the object that was originally in 'a' will have a unique reference

                //   embodied by the 'b' variable.



let z = b.x;    // Reference to 'x' property of the object.

                //   now, z object will have two references: one as a property,

                //   the other as the 'z' variable.



b = 'chrome';  // The object that was originally in 'b' has now zero

                //   references to it. It can be garbage-collected.

                //   However its 'a' property is still referenced by

                //   the 'z' variable, so it cannot be freed.



z = null;       // The 'a' property of the object originally in a

                //   has zero references to it. It can be garbage collected.

Limitations (Circular References)

Example

JavaScript garbage collector has limitations when it finds circular references. For example, consider the below example:

function myFunction() {

  const a = {};

  const b = {};

  a.x = b;        // a references b

  b.y = a;        // b references a

  return 'someString';

}

myFunction();

In the example demonstrated above, we have established two objects that reference each other, creating a reference cycle. This scenario is known as circular references. Once the execution of the myFunction function is finished, it will exit its scope. Although they will no longer be required at that stage, their assigned memory will be released. Consequently, the garbage collector will not deallocate their allocations.

The garbage collector employing reference counting does not identify these objects as reclaimable, as each retains a reference. Consequently, neither will be flagged for garbage collection. Circular references are a common cause of memory leaks in applications.

Internet Explorer versions 6 and 7 utilize reference counting garbage collectors, however, no contemporary engines rely on this method to address memory leaks caused by circular references.

Mark-and-sweep algorithm

The mark-and-sweep technique decreases reliance on the "object is no longer used" method by emphasizing the "object is unreachable" concept.

This strategy emphasizes the starting point, which is the set of objects known as the roots. The root, which is the global object in JavaScript, serves as the initial reference point for the garbage collector. It begins its process by identifying and tracing the objects that are directly linked to these roots. By traversing these paths, it establishes connections to all objects originating from the roots. Consequently, this method effectively distinguishes between reachable and non-reachable objects during the garbage collection process.

This algorithm represents an enhancement of the reference-counting algorithm. In this approach, an object with zero references will be identified as unreachable. Therefore, in this algorithm, an object will not remain valid if it is involved in a circular reference.

In 2012, modern web browsers started adopting the mark-and-sweep algorithm as the standard method for garbage collection. JavaScript has evolved significantly over the years, with all the enhancements based on this approach rather than the native "an object is no longer needed" method.

In the initial scenario, there were no two objects pointing to any resource post the function invocation. Consequently, they will be deemed unreachable by the garbage collector, allowing their memory to be retrieved.

Limitations:

At times, it might be necessary in the application to manually indicate which memory should be freed. Releasing the memory of an object involves intentionally making it unreachable to free up the memory.

It is not possible to manually initiate the JavaScript garbage collection process.

Summary:

JavaScript incorporates an effective garbage collection system to manage memory efficiently. The process of memory management in JavaScript is automated and operates behind the scenes without user intervention. Manual triggering of the JavaScript garbage collector is not possible.

Input Required

This code uses input(). Please provide values below: