• A Beginner’s Guide to Memoization with JavaScript
  • By Mahdhi Rezvi
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: samyu2000
  • Proofread: Regon-cao, Ashira97, PassionPenguin

An introduction to JavaScript Memoization

Being a software developer requires constant learning. There are always new things to learn, especially javascript-related technologies. As our applications become more complex, speed becomes more important. As the amount of code in an application increases, performance tuning is required. Memoization is a concept that helps you build efficient applications, even as they get bigger and bigger. Memoization concepts are closely related to pure functions and functional programming in JavaScript.

Keep in mind that Memoization is just a concept, not related to any programming language. In this article, we discuss Memoization from a JavaScript perspective.

What is a Memoization

Memoization, by definition, is a programming technique that stores the results of a complex operation of a function so that the next time the function is called with the same input, it quickly returns the saved results without repeated processing.

If you break this definition down further, you should note that there are three main points:

  • Caching results – Caching is a way to temporarily store data to speed up the next access.
  • Complex computation – this refers to complex computation or processing. Complexity means that the process consumes a lot of system resources or takes a long time, both of which are important metrics in the computer world.
  • The input data is the same — that’s a blunt statement. But it establishes a connection between Memoization and pure functions. In terms of basic concepts, a function is called pure if it always returns the same result for the same input data.

After breaking this concept down, we should have a basic idea of Memoization. If you still don’t understand, don’t worry, I’ll go into depth and make you understand.

When and why do I need to Memoize your functions?

Why is that?

Let’s start with why we need Memoize. Memoization can go a long way toward improving your performance when calling complex functions. When a function takes input, performs some complex operations and returns the output, the output value can be cached. If the function receives the same input again, it naturally returns the same output, rather than start all over again.

There’s a lot of information online about how to optimize performance using Memoization. You can also learn more by checking out the resources listed at the end of this article.

When?

Only pure functions can Memoize. It is not practical to Memoize a function that has the same input data but may produce different results. Take a look at this code.

Although the input data is the same, the output of each call to the function is different. Memoize such functions is moot.

Further, in these cases you may need to Memoize the function:

  • The function is recursive and the input data is repeated.
  • A condition that takes a lot of time or resources to call a function.

Focus on

There are three things you need to remember about Memoization. These prerequisites must be met for Memoization to make sense.

  • Pure functions – Although this has already been mentioned, it is important to note that in order to Memoize a function, the function must be pure.
  • Higher-order functions – This type of function returns another function that can be called again.
  • Closures – Because of closures and higher-order functions, the function’s internal cache can remember its value.

Learn the following examples to understand how these concepts are applied in practice.

The application of Memoization

A common example of the application of Memoization is the calculation of factorials. Let’s see.

In the example above, each call is recalculated. When factorial(100) is called the second time, the whole process is repeated. If we were doing Memoization here, we would not need to evaluate factorial(100) again since we have already cached it.

Let’s look at this example of using Memoization.

In this example, you can clearly see that the cached value is always taken. This makes it easy to skip calculations that have already been calculated, saved, and used a lot of resources.

If you look closely at the call, you will see that since there is no calculation involved, you quickly get the value of factorial(50). This is because factorial of 50 has been evaluated and cached in the memory space of factorial of 60.

You can run the example here.

Something to note about the example above

You can clearly see that the factorial function is a pure function because the output is always the same for the same input. You should also note that the Memoize function is a higher-order function because it returns a function that will be called in the future and will also use the function as an input parameter. Further, we can also see that since higher-order functions are being used, a closure is created that allows internally nested functions to access cached objects.

Now we can understand how to Memoize functions using three points.

Difference between Caching and Memoization

You may be wondering what the difference is between Caching and Memoization. In fact, Caching is a general term for various forms of Caching, such as HTTP Caching and image Caching. But Memoization is, for the most part, a specific type of cache that caches the return value of a function.

You’ll notice that I’ve already touched on the essentials of Memoization. Therefore, Caching is only a part of Memoization, not Memoization itself.

Memoization related libraries

There are libraries that you can use to memoize functions, but they all do Memoization in different ways.

  • Moize
  • Lodash
  • Underscore
  • Memoize Immutable and more.

You can take a look at all the libraries and their features in the Q&A section on Stack Overflow.

Do I need to memoize all of my functions?

Is not the

While Memoization can greatly improve the performance of your program, there are a few things you need to keep in mind. The cache stores the associated values, indicating that the data is being stored. If the input range of a function is too large, your cache will get bigger and bigger. Typically Memoization functions have a spatial complexity of O(n). Some algorithms can also be used to improve the spatial complexity of Memoization functions.

It’s important to understand that you have to balance two resources — time and space. While Memoization can reduce the time complexity of functions, on the other hand, it can increase the spatial complexity.

Therefore, I think Memoization of a function is an appropriate choice when it has a fixed range of input values and is certain that the function will be called repeatedly.


Thank you for reading this. Happy coding!

The related resources

  • Article by Philip
  • Article by Codesmith
  • Article by Divyanshu
  • Lecture Notes — Carnegie Mellon University
  • MDN Docs

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.