Skip to content

Best to optimize memory usage in JavaScript

By Rabin Lamichhane

Published: at 12:33 PM

Memory management in web development

Memory management is a critical aspect of web development that can significantly impact the performance and user experience of web applications. In this blog post, we’ll take a closer look at memory management in web development and explore some strategies for optimizing memory usage in JavaScript.

When we talk about memory management in web development, we’re mainly referring to the way that web browsers allocate and deallocate memory for web pages and applications. The main goal of memory management is to ensure that the browser uses memory efficiently and avoids running out of memory, which can cause performance issues or even crashes.

One key concept in memory management is garbage collection. Garbage collection is the process by which the browser automatically frees up memory that is no longer needed. The browser keeps track of all the objects that have been created by a web page or application and periodically scans for objects that are no longer in use, freeing up their memory.

To optimize memory usage in web development, there are several strategies that develop

  1. Avoid global variables. Global variables stay in memory throughout the lifetime of a web page or application, even if they are not needed. To minimize memory usage, developers should avoid using global variables and instead use local variables or function closures to limit the scope of their variables.

  2. Use event delegation. When adding event listeners to a large number of elements, using event delegation can help reduce memory usage. This involves adding a single event listener to a parent element and then using the event object to determine which child element was clicked or triggered the event.

  3. Use efficient data structures. When dealing with large amounts of data, choosing the right data structure can have a big impact on memory usage. For example, using arrays instead of objects can be more memory-efficient for storing ordered lists of data.

  4. Use object pooling. Object pooling involves reusing objects instead of creating new ones. This can be particularly useful when dealing with objects that are frequently created and destroyed, such as DOM elements or canvas objects.

  5. Use a profiler. Profiling tools like Chrome’s DevTools can help developers identify memory leaks and other performance issues in their JavaScript code. By analyzing their code’s memory usage, developers can identify areas where they can optimize their code and reduce memory usage.

Avoid global variables.

Without using the tip:

var x = 5; // Global variable
function doSomething() {
  // Some code that uses x
}

With the tip:

function doSomething() {
  var x = 5; // Local variable
  // Some code that uses x
}

Use event delegation:

Without using the tip:

var elements = document.querySelectorAll(".my-element");
for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener("click", function () {
    // Some code that handles the click event
  });
}

With the tip:

document.addEventListener("click", function (event) {
  if (event.target.classList.contains("my-element")) {
    // Some code that handles the click event
  }
});

Use efficient data structures:

Without using the tip:

var data = {
  item1: "value1",
  item2: "value2",
  item3: "value3",
};

With the tip:

var data = ["value1", "value2", "value3"];

Use object pooling

Without using the tip:

function createNewElement() {
  var element = document.createElement("div");
  // Some code that sets up the new element
  return element;
}

var newElement = createNewElement(); // Create a new element
// Some code that uses the new element
// When finished, remove the element from the DOM and destroy it

With the tip:

var elementPool = [];
function createNewElement() {
  if (elementPool.length > 0) {
    return elementPool.pop(); // Reuse an existing element
  } else {
    var element = document.createElement("div");
    // Some code that sets up the new element
    return element;
  }
}

var newElement = createNewElement(); // Create a new element or reuse an existing one
// Some code that uses the new element
// When finished, remove the element from the DOM and return it to the pool
elementPool.push(newElement);

Use a profiler

console.profile("My code profiler");
// Some code that may have performance or memory issues
console.profileEnd();

WeakMap and WeakSet

WeakMap is a type of map in which the keys are weakly referenced. This means that if a key object is no longer being used anywhere else in the program, it can be garbage collected and the corresponding value in the WeakMap will be automatically removed as well. This can help prevent memory leaks caused by keeping references to objects that are no longer needed.

WeakSet is similar to WeakMap, but it stores a set of objects that are also weakly referenced. This can be useful for keeping track of a collection of objects that should be automatically removed from memory when they are no longer being used.

It’s important to note that both WeakMap and WeakSet have limitations compared to their non-weak counterparts. For example, because keys in WeakMap are weakly referenced, they must be objects (or null) and not primitives like strings or numbers. Additionally, because objects in WeakSet are weakly referenced, they cannot be iterated over or counted like regular sets.

Example 1

Caching computed values

Without WeakMap:

const cache = {};
function expensiveOperation(input) {
  if (input in cache) {
    return cache[input];
  }
  // perform expensive computation and store result in cache
  const result = // ...
    (cache[input] = result);
  return result;
}

With WeakMap:

const cache = new WeakMap();
function expensiveOperation(input) {
  if (cache.has(input)) {
    return cache.get(input);
  }
  // perform expensive computation and store result in cache
  const result = // ...
    cache.set(input, result);
  return result;
}

Using a WeakMap allows for automatic cleanup of cache entries that are no longer needed.

Example 2: Tracking objects for cleanup

Without WeakSet:

class TemporaryObject {
  constructor() {
    this.cleanupToken = {};
    temporaryObjects.push(this.cleanupToken);
  }
  cleanup() {
    // clean up resources used by object
  }
}
const temporaryObjects = [];
// create and use temporary objects
const obj1 = new TemporaryObject();
const obj2 = new TemporaryObject();
// ...
// later, remove all temporary objects and clean up their resources
temporaryObjects.forEach(token => {
  const obj = temporaryObjects.find(obj => obj.cleanupToken === token);
  obj.cleanup();
});
temporaryObjects.length = 0;

With WeakSet:

class TemporaryObject {
  constructor() {
    temporaryObjects.add(this);
  }
  cleanup() {
    // clean up resources used by object
  }
}
const temporaryObjects = new WeakSet();
// create and use temporary objects
const obj1 = new TemporaryObject();
const obj2 = new TemporaryObject();
// ...
// later, remove all temporary objects and clean up their resources
temporaryObjects.forEach(obj => obj.cleanup());

Using a WeakSet allows for automatic cleanup of objects that are no longer being used, without the need for a manual cleanup step.

In conclusion, managing memory is an important aspect of web development, as it can have a significant impact on the performance and stability of your applications. JavaScript provides several tools for managing memory, including garbage collection, memory profiling, and data structures like WeakMap and WeakSet.

See also

Memory management - JavaScript | MDN *Low-level languages like C, have manual memory management primitives such as malloc() and free(). In contrast…*developer.mozilla.org WeakMap - JavaScript | MDN *A WeakMap is a collection of key/value pairs whose keys must be objects, with values of any arbitrary JavaScript type…*developer.mozilla.org WeakSet - JavaScript | MDN *Functions that call themselves recursively need a way of guarding against circular data structures by tracking which…*developer.mozilla.org

If you have any queries, feel free to contact us on https://discord.gg/RDU62RrFe3