Memoization in JavaScript? And how to apply it to get better code performance.
Tags: javascript, performance, beginners, webdev
Published: 2022-02-20 17:01:35




As a programmer, we always want to write code that is robust and gives us better performance. But sometimes we face performance issues due to not applying good optimization techniques. One such technique is **Memoization**. Memoization offers notable performance benefits when dealing with a function that has **repeated** parameters.
In this article, I'm going to talk about Memoization, how you can implement it and when it should be used.

|                                   **Table of contents**                                   |
| :---------------------------------------------------------------------------------------: |
|                                                                                           |
|                        <a href="#prerequisites"> Prerequisites</a>                        |
|                  <a href="#what-is-memoization">What is Memoization</a>                   |
|             <a href="#implementing-memoization"> Implementing Memoization</a>             |
|                <a href="#how-memoization-works">How memoization works </a>                |
| <a href="#normal-function-vs-memoized-function">Normal function vs Memoized Function </a> |
|                            <a href="#use-cases">Use Cases </a>                            |
|      <a href="#third-party-libraries-for-memoization">Libraries for Memoization</a>       |
|                            <a href="#tradeoffs">Tradeoffs </a>                            |
|                           <a href="#references">References </a>                           |
|                           <a href="#conclusion">Conclusion </a>                           |


# Prerequisites

Before you begin reading, it will be great to know the followings:

- JavaScript Fundamentals
- [Closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
- [Pure Function](https://www.freecodecamp.org/news/what-is-a-pure-function-in-javascript-acb887375dfe/)
- [Higher-Order Function](https://www.codecademy.com/learn/game-dev-learn-javascript-higher-order-functions-and-iterators/modules/game-dev-learn-javascript-iterators/cheatsheet)

So let's get started!!!

# What is memoization?

From Wikipedia:

> In computing, memoization or memoisation is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

So, Memoization is an optimization technique that can be used to **reduce extensive**(time-consuming) calculations by saving previous input to something called `cache` and returning the **result** from it. When a memoized function is given the same input again, it will return the cached result without calculating from the start. Thus saving code execution time and memory.

As you can guess, Memoization is not only **limited** to JavaScript but is also widely supported by many other languages. It's a common concept in the programming world.

# Implementing Memoization

Before seeing how Memoization works, let's look at a simple example that will demonstrate how Memoization can help us to get better performance. 
 Consider the following function which returns the square of a number.

#### Normal Function

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcsl7cj2060gpjcfh5yi.png)
In case if you are not familiar with `console.time()` and `console.timeEnd` , they are used to **track** how long an operation takes. Read more about them on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/console/time).

Here, I've invoked the function with the same input _four_ times. Here is its completion time:

![time](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0qy2pt0jafwhze2exwu.png)

| Invocations | Time Taken |
| ----------- | ---------- |
| First       | 9.331ms    |
| Second      | 2.336ms    |
| Third       | 1.397ms    |
| Fourth      | 0.137ms    |

Later we'll compare this result against the memoized result.

#### Memoized Function

Now we are going to implement Memoization in the `getSquare` function. Remember that to memoize a function, it should be **pure** so that return values are the same for the same inputs every time.

Take a look at the following function:

![normal function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6rznf3sa6219hl933ok.png)

###### Demo Output:
![demo output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mlfhjrfmzix3irewm7ab.png)

# How Memoization works?

The principal to making a function **memoized function** is to store its last input and output. In JavaScript environment, Memoization heavily relies on **Closure** and **Higher-Order Functions**.

#### Code breakdown of `memoSquare()` function:

- In line 3 we have variable named `cache` to store previous inputs.
- In Line 5 we return the whole **memoized** function.
- In Line 7 we check if the input is in the `cache`. If so, we return the cached value.`cache` can remember the values because of the **closure** it's implemented in. And this only works because the function we're working with is a **pure** function.
- If we check the output of cache in line 9 of **Output**, we'll see that `cache` object is containing all the inputs only once.For example, We have inputted value 4 multiple times but it only storing it **once**. If the current inputted value is in the cache then it simply returns value. Check the <a href="#demo-output">Demo output</a>
  screenshot.
- From line 13 we write our function logic. In here it runs a `for` loop and simply returns a square of a number.
- In line 15 we cache/store our new input value to the `cache` object.

Now lets checkout the **completion** time of `memoSquare()` function.

#### Invoking the function multiple times with same value:


![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfhzrt44jwxwmd23551z.png)

#### Result:


![memo function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wpj1j3c8w4cpqxvpffnb.png)

| Invocations | Time Taken |
| ----------- | ---------- |
| First       | 7.741ms    |
| Second      | 0.056ms    |
| Third       | 0.52ms     |
| Fourth      | 0.045ms    |

---

### Normal function vs Memoized Function:


![normal vs memoized](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/auha86vmbablmod1djls.PNG)

From the comparison table, you can see how Memoization grants us better performance aka execution time each time it is called with the same value. It cuts down the heavy calculations for a previous value. So it's a good idea to memoize a function that does heavy computations or is expensive on **time and memory**.

# Use Cases

You can use Memoization in the following cases:

- Repeated invocations of a function.
- When you have a wide range of input values.
- You have an idea what will be the possible inputs.
- Functions that involves mathematically heavy operations.
- In recursive functions.

---

# Tradeoffs

Like any other optimization technique, There are limitations of Memoization. In some cases, improper use of Memoization can actually harm performance. Memoization works by storing old results and it has to be stored somewhere. As a consequence, memoized functions consume **additional** memory. 
Memoization is appropriate for functions where there’s a high chance that the same input values will be used regularly. So Memoization may not be ideal for **infrequently** called or fast executing functions.

# Third-party libraries for Memoization

You can use following third party libraries to implement Memoization:

- [fast-memoize](https://github.com/caiogondim/fast-memoize.js)
- [memoize-one](https://github.com/alexreardon/memoize-one)
- [Lodash_memoize](https://lodash.com/docs/4.17.15#memoize)

# References:

Followings are some resources to help you out:

- [Memoization](https://en.wikipedia.org/wiki/Memoization)
- [Closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
- [Pure Function](https://www.freecodecamp.org/news/what-is-a-pure-function-in-javascript-acb887375dfe/)
- [Higher-Order Functions](https://www.codecademy.com/learn/game-dev-learn-javascript-higher-order-functions-and-iterators/modules/game-dev-learn-javascript-iterators/cheatsheet)
- [console.time()](https://developer.mozilla.org/en-US/docs/Web/API/console/time) / [console.timeEnd()](https://developer.mozilla.org/en-US/docs/Web/API/console/timeEnd)
- [Memoization in React](https://www.sitepoint.com/implement-memoization-in-react-to-improve-performance/)

# Conclusion

Memoization is a form of caching which gives performance improvements where a function is called many times with the same input. Applying Memoization will help you to write performant and robust code. But you have to be careful about not implementing it in an irrelevant scenario.

That's all for today. Thank you for reading, and don't forget to connect on [LinkedIn](https://www.linkedin.com/in/md-rakibur-rahman-talukder-04666519a/) or [Twitter](https://twitter.com/RakibRahman06)

**If you have any questions or thoughts, please leave a comment!?**