Altcademy - a Forbes magazine logo Best Coding Bootcamp 2023

What is Memoization in JavaScript?

In this post, we will explore the concept of memoization in JavaScript. We will start by understanding what memoization is, why it is important, and how it can improve the performance of your JavaScript code. We will also look at some examples to help you understand this concept better.

What is Memoization?

Memoization is a programming technique used to optimize the execution time of a function by caching its results for a given set of input parameters. In simpler terms, memoization is a way to remember the result of a function call for a specific set of inputs. If the function is called again with the same inputs, the cached result is returned instead of recomputing the result.

Memoization is particularly useful when dealing with expensive or time-consuming computations, as it can significantly reduce the execution time of your code.

Now, let's dive into the concept with an analogy.

Analogy: Solving a Math Problem

Imagine that you're a student in a math class, and your teacher has given you a set of problems to solve. You go through each problem, one by one, and work out the solutions. After completing the problems, you realize that some of them are actually the same, just written differently. If you had noticed this earlier, you could have saved time by just writing down the answer you had already solved, instead of solving the same problem again.

This is similar to memoization in programming. When a function is called multiple times with the same inputs, instead of repeating the calculations, we store the results for those inputs and use the stored results when the same inputs are encountered again.

Memoization in JavaScript

JavaScript does not have built-in support for memoization, but we can easily implement it using objects, maps, or even arrays (depending on the use case). Let's look at an example to understand this better.

Example: Fibonacci Series

The Fibonacci series is a sequence of numbers where each number is the sum of the two preceding ones, usually starting with 0 and 1. The sequence goes like this: 0, 1, 1, 2, 3, 5, 8, 13, and so on.

A common approach to finding the nth number in the Fibonacci series is using recursion. Here's an example of a simple recursive function that computes the nth Fibonacci number:

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

This function works fine for small values of n. However, as n increases, the execution time grows exponentially, making it very inefficient. This is because the function recalculates the same Fibonacci numbers multiple times.

To solve this problem, we can use memoization. Let's modify our fibonacci function to use memoization:

function memoizedFibonacci() {
  const cache = {};

  return function fib(n) {
    if (n <= 1) {
      return n;
    }

    if (!cache[n]) {
      cache[n] = fib(n - 1) + fib(n - 2);
    }

    return cache[n];
  };
}

const fibonacci = memoizedFibonacci();

In this example, we have created a memoizedFibonacci function that returns a fib function. The fib function uses a cache object to store the results of previous calculations.

When the function is called with a new input, it checks if the result for that input is already present in the cache. If it is, the cached result is returned. If not, the result is calculated, stored in the cache, and then returned.

By using memoization, we have significantly improved the performance of our Fibonacci function.

When to use Memoization

Memoization can be a powerful technique for optimizing your code, but it is not always the best solution. Here are some factors to consider when deciding whether to use memoization:

Function calls with repetitive inputs: Memoization is most effective when a function is called multiple times with the same inputs. If the inputs are always different, memoization will not provide any performance benefits.

Expensive computations: Memoization is most useful when dealing with functions that perform complex or time-consuming calculations. If the function is relatively simple and fast, memoization may not be worth the added complexity.

Memory constraints: Memoization involves storing results in memory, which can be a problem if you are working with limited memory resources. If your function has a large number of possible inputs and you are concerned about memory usage, you may need to consider other optimization techniques or use a caching strategy with a limited size.

Conclusion

In this post, we learned about memoization, a technique used to optimize the execution time of a function by caching its results for a given set of input parameters. We also looked at an example of how to implement memoization in JavaScript using a Fibonacci series function.

Memoization can be a powerful optimization tool, but it is important to consider the specific use case and the trade-offs involved before implementing it in your code.

Now that you understand the concept of memoization, you can start identifying opportunities to use it in your own JavaScript projects to improve the performance and efficiency of your code.