Speed Up Repeated Calculations with Memoization in JavaScript
How to remember results so your functions don’t repeat work
Get Quratulayn’s stories in your inbox
Join Medium for free to get updates from this writer.
Some functions do the same work over and over. Imagine a function that calculates a student’s percentage from their marks. If the same mark gets entered many times, why calculate the answer again every time? Memoization solves this by saving results the first time they’re computed and returning the saved value on later calls.
The Example
Here is a simple function that calculates a percentage out of a total of 520 marks:
let totalMarks = 520;
let calculatePercentage = (obtainedMarks) => {
return (obtainedMarks * 100) / totalMarks;
};
console.log(calculatePercentage(501).toFixed(2)); // 96.34This function is cheap to run, but the idea scales to expensive calculations too.
Building a Memoize Function
memoize takes any function and returns a new version of it that remembers past results:
function memoize(fn) {
let memory = {};
return function(...args) {
let key = args.join(",");
if (key in memory) {
return memory[key];
} else {
let result = fn(...args);
memory[key] = result;
return result;
}
};
}Here is how it works:
- The memory is created once, outside the returned function. It persists between calls, just like a variable in a closure.
- When the function is called, it checks whether the argument is already a key in the memory.
- If it is, the saved result is returned and
fnnever runs. - If it isn’t,
fnruns, the result is stored, and then it's returned.
Using It
const memoizedPercentage = memoize(calculatePercentage);
console.log(memoizedPercentage(501)); // computed
console.log(memoizedPercentage(501)); // from cache
console.log(memoizedPercentage(300)); // computedTo see the difference, add a counter to the original function:
let calls = 0;
const countedPercentage = memoize((obtainedMarks) => {
calls++;
return (obtainedMarks * 100) / totalMarks;
});
countedPercentage(501);
countedPercentage(501);
countedPercentage(300);
console.log(calls); // 2, not 3The repeated call with 501 never reached the original function.
Why Use a Map?
You may see memoize written with a plain object instead:
const memory = {};
if (key in memory) { ... }This works for many cases, but it has a flaw. Plain objects inherit properties from Object.prototype, so "toString" in {} returns true. A Map avoids this problem and accepts any kind of key, so it's the safer choice.
When to Use Memoization
Memoization is useful when:
- The function is pure, meaning the same input always gives the same output.
- The calculation is expensive, such as complex math or processing large data.
- The same inputs are requested often.
It’s less useful when inputs rarely repeat, since the cache only adds memory use without saving time.
Key Takeaway
Memoization trades a little memory for speed. By keeping a cache outside your function, you can skip work you’ve already done. Once you understand closures, as used in once, memoization is a natural next step.









