Understanding Memoization in JavaScript and Its Benefits

comprehensive guide when and how to use Memoization in JavaScript: Best Practices and Examples.

Amit Sharma
5 min readApr 18, 2023

Every one of us has been frustrated by an app that simply takes too long to load. Slow performance may be quite annoying, whether it’s a website that takes too long to render, an app that takes forever to open, or a function in an application that takes too long to execute. Not only is it annoying for customers, but it may also cost businesses money and damage a company’s reputation.

One of the ways to tackle the problem of slow applications is to use memoization, a technique that can help optimize and speed up function execution.

What is Memoization?

In JavaScript, Memoization is a potent method for enhancing function performance. Involves caching the results of expensive function calls, so that they can be promptly accessed rather than having to be recalculated each time the function is invoked. By using memoization, you can drastically reduce the amount of time and resources your code consumes, and create more efficient and scalable applications.

For illustration, suppose you have a function that takes a while to compute a number’s factorial. If you use memoization, the function will store the calculated result and use it each time the same number is entered. As a result, the function will execute considerably faster if you call it again with the same number since it will retrieve the saved result from the cache rather than computing it from scratch.

In this post, we’ll examine the advantages of JavaScript’s memoization concept in depth. We’ll go through how it functions, when to use it, and give usage examples. You’ll have a thorough knowledge of how memoization can enhance the functionality of your code by the time you finish reading this article.

Why use Memoization ?

Let’s say you have a function that calculates the nth number in the Fibonacci sequence:

 function fib(n) {
if (n <= 1) {
return n
}
return fib(n - 1) + fib(n - 2)
}

fib(9) // outputs: 34 default: 0.13916015625 ms

This function works fine for small values of n and takes 0.13ms to execute, but as n gets larger, it can take a long time to execute. For example, computing fib(40) takes several milliseconds to complete, while fib(50) takes several seconds.

function fib(n) {
if (n <= 1) {
return n
}
return fib(n - 1) + fib(n - 2)
}
console.time()
fib(40) // outputs: 102334155 default: 1380.770751953125 ms
console.timeEnd()

In the above example you can see, the fib(40)took 1380.77ms to execute. If this function fib(40) runs again and again with the same argument , it will take several milliseconds to execute This can lead to performance issues and need to be optimized. By using Memoization we can lower the computation timing and optimize the function fib() .

To optimize this function using memoization, we can cache the results of each computation using an object:


const memoize = (func) => {
const cache = {};
}

In the above example , I have created a function called “memoize” that takes another function as an argument and has an empty object named “cache” in it.

Let’s continue with memoize function:

const memoize = (func) => {
const cache = {};
return (...args) => {
const key = args[0];
if (key in cache) {
return cache[key];
} else {
const result = func(key);
cache[key] = result;
return result;
}
}
}

The memoized function returned by memoize has a cache object that is used to store the results of previous calls to func. The cache object is an empty object initially.
This implementation of memoize uses an arrow function and the rest parameter syntax (...args) to capture an arbitrary number of arguments passed to the memoized function.

It then uses object property lookup to check if the [key] exists in the cache object, and the in operator to determine if the [key] is present in the object. If the [key] exists in the cache object, the cached result is returned.

Otherwise, the input function is called with the arguments, and the result is stored in the cache object (cache[key] = result;) using the first argument as the [key].

Here is the full code -

 function fib(n) {
if (n <= 1) {
return n
}
return fib(n - 1) + fib(n - 2)
}

const memoize = (func) => {
const cache = {};
return (...args) => {
const key = args[0];
if (key in cache) {
return cache[key];
} else {
const result = func(key);
cache[key] = result;
return result;
}
}
}


const result = memoize(fib)
console.time()
console.log(result(40)); //Output 832040 "default: 1390.040771484375 ms"
console.timeEnd()

console.time()
console.log(result(40)); //Output 832040 "default: 0.041015625 ms"
console.timeEnd()

And now when you run memoize with the argument of fib(40) multiple times you can see the memoized version of the function is significantly faster than the original function, taking only 0.04 ms to compute fib(40) instead of 1390.04 ms.

This is just one example of how memoization can be used to optimize function execution in JavaScript. By caching the results of expensive function calls, you can greatly improve the performance of your code and create more efficient and scalable applications.

When to use Memoization ?

Memoization can be used in situations where you have a function that is called frequently with the same input parameters and takes a long time to compute. By caching the results of previous function calls, you can avoid recomputing the same result multiple times.

Here are some common scenarios where memoization can be useful:

  1. Recursive functions: Recursive functions can often benefit from memoization since they tend to call themselves repeatedly with the same input parameters.
  2. Expensive calculations: If your function performs a computationally expensive operation, such as sorting a large array or making an API call, memoization can be used to avoid repeating the operation for the same input parameters.
  3. Immutable data: If your function operates on immutable data, memoization can be used to avoid recomputing the function result for the same input parameters since the result will always be the same.
  4. Data retrieval: If your function retrieves data from a database or external source, memoization can be used to avoid making the same request multiple times for the same input parameters.

In conclusion, memoization is a valuable tool to have in your optimization toolkit, and can help you create more efficient and scalable applications.

It’s important to note that memoization should be used with caution since it can lead to memory leaks if not implemented correctly. Make sure to use appropriate caching strategies and limit the size of your cache to avoid storing too much data in memory.

Thanks for reading ! I hope you enjoyed learning about this fantastic optimization technique.
If you like it , do consider sharing it with your friends, I’d really appreciate that🧡.

Learn advanced concept of javascript.

Thank you 🙂

--

--

Amit Sharma

Front-end developer sharing coding tips and life lessons. Join me for tech insights and personal growth advice to enhance your career and life.