Memoization in JavaScript

Memoization is a programming technique that attempts to increase a function’s performance by caching its previously computed results. Because JavaScript objects behave like associative arrays, they are ideal candidates to act as caches. Each time a memoized function is called, its parameters are used to index the cache. If the data is present, then it can be returned, without executing the entire function. However, if the data is not cached, then the function is executed, and the result is added to the cache.

Memoization helps us reduce the time taken and amount of resources consumed in the execution of “expensive function calls”.

What is an expensive function call?

Memoization uses caching to store the results of our function calls for quick and easy access at a later time.

Thus, when an expensive function has been called once, the result is stored in a cache such that whenever the function is called again within our application, the result would be returned very quickly from the cache without redoing any calculations.

Let’s look at an example:

function factorial(n) {
// Calculations: n * (n-1) * (n-2) * ... (2) * (1)
return factorial
}

let’s find factorial(50). The computer will perform calculations and return us the final answer.

When that’s done, let’s find factorial(51). The computer again performs a number of calculations and gets us the result, but you might have noticed that we’re already repeating a number of steps that could have been avoided. An optimized way would be.

factorial(51) = factorial(50) * 51

Our function performs the calculations from scratch every time it’s called.

factorial(51) = 51 * 50 * 49 * ... * 2 * 1

If somehow our factorial the function could remember the values from its previous calculations and use them to speed up the execution? Memoization, a way for our function to remember (cache) the results. A memoized function is usually faster because if the function is called subsequently with the previous value(s), then instead of executing the function, we would be fetching the result from the cache.

Simple memoized function.

// a simple function to add something
const add = (n) => (n + 10);
add(9);
// a simple memoized function to add something
const memoizedAdd = () => {
let cache = {};
return (n) => {
if (n in cache) {
console.log('Fetching from cache');
return cache[n];
}
else {
console.log('Calculating result');
let result = n + 10;
cache[n] = result;
return result;
}
}
}
// returned function from memoizedAdd
const newAdd = memoizedAdd();
console.log(newAdd(9)); // calculated
console.log(newAdd(9)); // cached

memoizedAdd returns a function which is invoked later.

cache can remember its values since the returned function has a closure over it.

Resources:

https://blog.bitsrc.io/understanding-memoization-in-javascript-to-improve-performance-2763ab107092