As our systems mature and begin to do more complex calculations, the need for speed grows, and process optimization becomes a need. When we overlook this issue, we end up with applications that take a long time to run and demand a large number of system resources.
In this article, we are going to look at memoization which is one technique that can help us significantly reduce processing time if done the right way.
Memoization: Memoization is a technique for speeding up applications by caching the results of expensive function calls and returning them when the same inputs are used again.
Let us try to understand this by breaking the definition into small parts.
- Expensive Function Calls: Time and memory are the two most important resources in computer applications. As a result, an expensive function call is one that consumes large amounts of these two resources due to extensive calculation during execution.
- Cache: A cache is just a temporary data store that stores data in order to serve future requests for that data more quickly.
Importance of Memoization: When a function is given in input, it performs the necessary computation and saves the result in a cache before returning the value. If the same input is received again in the future, it will not be necessary to repeat the process. It would simply return the cached answer from the memory. This will result in a large reduction in a code's execution time.
Memoization in Javascript: In JavaScript, the concept of memorization is based mostly on two ideas. They are as follows:
- Closures
- Higher-Order Functions
Closures: Before talking about closure, let's take a quick look at the concept of lexical scope in JavaScript. Lexical scoping defines the scope of a variable by the position of that variable declared in the source code.
Example:
JavaScript
let hello = "Hello";
function salutation() {
let name = "Aayush";
console.log(`${hello} ${name}!`);
}
In the above code:
- The variable hello is a global variable. It can be accessed from any location, including the salutation() function.
- The variable name is a local variable that can only be accessed within the salutation() function.
According to lexical scoping, the scopes can be nested and the inner function can access the variables declared in its outer scope. Hence in the code below, the inner function greet() has access to the variable name.
JavaScript
function salutation() {
let name = "Aayush";
function greet() {
console.log(`Hello ${name}!`);
}
greet();
}
Now let’s modify this salutation() function and rather than invoking the function greet(), we return the greet() function object.
JavaScript
function salutation() {
let name = 'Aayush';
function greet() {
console.log(`Hello ${name}!`);
}
return greet;
}
let wish = salutation();
wish();
If we run this code, we will get the same output as before. However, it's worth noting that a local variable is generally only present during the function's execution. It means that when salutation() execution is completed, the name variable is no longer accessible. In this case, when we execute wish(), the reference to greet(), the name variable still exists. A closure is a function that preserves the outer scope in its inner scope.
Higher-Order Functions: Higher-order functions are functions that operate on other functions by taking them as arguments or returning them. For example, in the above code, salutation() is a higher-order function.
Now, using the famous Fibonacci sequence, let's examine how memoization makes use of these concepts.
Fibonacci Sequence: The Fibonacci sequence is a series of numbers that begins with one and ends with one, following the rule that each number (called a Fibonacci number) is equal to the sum of the two numbers before it.
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
A simple recursive solution to this problem would be:
JavaScript
function fibonacci(n) {
if (n < 2)
return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
If we were to plot the recursion tree for the above function when n=4, it would look like this,
As you may notice, there are too many redundant computations.
Let’s try to fix this with memoization.
JavaScript
function memoisedFibonacci(n, cache) {
cache = cache || [1, 1]
if (cache[n])
return cache[n]
return cache[n] = memoisedFibonacci(n - 1, cache) +
memoisedFibonacci(n - 2, cache);
}
We change the function in the code sample above to accept an optional argument called cache. We use the cache object as a temporary memory to store Fibonacci numbers with their associated indices as keys, which can then be retrieved as needed later in the execution.

If we plot the execution time, for both versions of the Fibonacci function, it is quite evident that the employment of the memoization technique leads to significant time reduction.
Practical Example: Javascript Memoization for a Web Response: To demonstrate this, we'll use an example Idioms API. It is a simple REST API built using Node.js.
Response times before Memoization: Following is a simple Express.js route that returns all of the idioms stored within the API. In this situation, each call will result in a database query.
JavaScript
import express from 'express';
const router = express.Router();
import { getAllIdioms } from '../services/database.js';
router.get('/', async function(req, res, next) {
try {
res.json(await getAllIdioms());
} catch (err) {
console.log('Error while getting idioms ', err.message);
res.status(err.statusCode || 500).json({
'message': err.message
});
}
})
Let's have a look at how long it takes for this approach to respond. I ran a quick load test using the Vegeta load testing tool.

Response times after Memoization: Now let’s modify the above code to add memoization. For the purposes of this illustration, I've used the p-memoize package.
JavaScript
import express from 'express';
const router = express.Router();
import { getAllIdioms } from '../services/database.js';
import pMemoize from 'p-memoize';
const ONE_MINUTE_IN_MS = 60000;
const memGetAllIdioms = pMemoize(getAllIdioms, { maxAge: ONE_MINUTE_IN_MS });
router.get('/', async function (req, res, next) {
try {
res.json(await memGetAllIdioms());
} catch (err) {
console.log('Error while getting idioms ', err.message);
res.status(err.statusCode || 500).json({'message': err.message});
}
})
As a result,

When compared to the previous graph, we can observe that the Express.js route that uses memoization is significantly faster than the non-memoize equivalent.
Similar Reads
JavaScript Linked List Programs JavaScript Linked List Programs contain a list of articles based on programming. Linked List is a linear data structure that stores data in linearly connected nodes. Linked lists store elements sequentially, but doesnât store the elements contiguously like an array. S. NoArticles1JavaScript Program
5 min read
Explain Implement a memoization helper function What is memoization? It is a programming technique that is used to increase the efficiency of function by storing the previous values that function has already been calculated. It increases the program efficiency by caching the results of the function calls. We often waste time by calling the functi
5 min read
JavaScript Map Coding Practice Problems Maps are an essential data structure used for storing key-value pairs. They provide efficient lookups, insertions, and deletions, and are widely used for implementing dictionaries, caches, and many other applications. This curated list of JavaScript Map Coding Practice Problems will help you master
2 min read
What is Memoization in React ? Memoization is a powerful optimization technique used in React to improve the performance of applications by caching the results of expensive function calls and returning the cached result when the same inputs occur again. In this article, we will learn more about the concept of memoization and its
6 min read
Lodash _.memoize() Method Lodash _.memoize() method is used to memorize a given function by caching the result computed by the function. If the resolver is issued, the cache key for storing the result is determined based on the arguments given to the memoized method. By default, the first argument provided to the memoized fu
2 min read
How to write a simple code of Memoization function in JavaScript ? Memoization is a programming technique that we used to speed up functions and it can be used to do whenever we have an expensive function ( takes a long time to execute). It relies on the idea of cache {}. A cache is just a plain object. It reduces redundant function expression calls. Let's understa
3 min read
JavaScript Heap Coding Practice Problems Heaps are an essential data structure in JavaScript used for efficiently managing priority-based tasks. A Heap is a specialized tree-based structure that allows for quick retrieval of the smallest or largest element, making it useful for priority queues, scheduling algorithms, and graph algorithms l
2 min read
What are In-Memory Caches? In-memory caches are essential tools in modern computing, providing fast access to frequently used data by storing it in memory. This article explores the concept of in-memory caches, their benefits, and their role in enhancing system performance and scalability. Important Topics for In-Memory Cache
12 min read
Java @Retention Annotations In Java, annotations are used to attach meta-data to a program element such as a class, method, instances, etc. Some annotations are used to annotate other annotations. These types of annotations are known as meta-annotations. @Retention is also a meta-annotation that comes with some retention polic
3 min read
Recursion in Java In Java, Recursion is a process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. Using a recursive algorithm, certain problems can be solved quite easily. A few Java recursion examples are Towers of Hanoi (TOH)
6 min read