Memoize
Prompt
Your task is to write a JavaScript function named memoize.
This function should take in another function as an argument and return a memoized version of it.
Solution
Explanation 🧠
-
The
memoizefunction is a higher-order function that takes another function fn as an argument. -
Inside the
memoizefunction, an emptyMapinstancecacheis created, which will be used to store the memoized results. -
The
memoizefunction returns a new function using an arrow function syntax. -
Inside the returned function, the arguments passed to the function are stringified using
JSON.stringifyto create a key for thecacheMap. -
If the key exists in the
cacheMap (checked usingcache.has(key)), it means the function has been called with those arguments before, so it simply returns the cached result from the Map usingcache.get(key). -
If the key doesn't exist in the
cacheMap, it means the function hasn't been called with those arguments before, so it calls the original functionfnwith the given arguments using the spread syntaxfn(...args), stores the result in thecacheMap usingcache.set(key, result), and returns the result. -
The first time
memoizedSquare(140)is called, the memoized function doesn't find the result in thecacheobject, so it calls the originalsquarefunction with 140 as the argument, calculates the result, stores it in thecacheobject, and returns the result. -
The second and third times
memoizedSquare(140)is called, the memoized function finds the result in thecacheobject using the key"140", and it simply returns the cached result without calling the originalsquarefunction again.
The Map provides better performance for key-value storage and retrieval compared to objects, especially when dealing with non-string keys.
⬆️ Level up #1 (Measure Performance)
How can you measure the time taken by each operation to evaluate the effectiveness of memoization?
Solution
Explanation 🧠
To evaluate the benefits of memoization, one can use the console.time() and console.timeEnd() functions to compare the duration of operations conducted with and without the application of memoization.
For instance, in the example provided above, we are calculating the square of a number. The initial computation requires a significant amount of time because the result isn't initially cached. However, if one inspects the console logs, they'll notice that subsequent computations are considerably quicker. This speed is due to the results now being stored in the cache, enabling the function to retrieve them directly from the cache rather than recomputing them.
Note 📄
Imagine you're cooking Palak Paneer, a delicious Indian vegetarian dish, and you want to time how long it takes. Here's how you'd do it:
- Start the stopwatch when you begin cooking. In our code, we'll call
console.time('Cooking Palak Paneer') - Cook your dish. In the JavaScript world, this represents any task you want to time. It could be a complex calculation, loading data, or anything that requires time to complete.
- Stop the stopwatch when you finish. In the code, you'll call
console.timeEnd('Cooking Palak Paneer')
console.time('Cooking Palak Paneer'); // Start the stopwatch (or timer)
// This is where you "cook" in your code, i.e., perform the operation you're timing.
for (let i = 0; i < 100000; i++) {
// Here, we're just looping many times as a placeholder for the cooking process.
}
console.timeEnd('Cooking Palak Paneer'); // Stop the stopwatch (or timer)When you run this code, the console (think of it as your digital kitchen timer) will tell you how long it took to "cook the Palak Paneer". You'll see a message something like this: "Cooking Palak Paneer: 35ms". This means it took 35 milliseconds to run the code between the start and end commands. Keep in mind this is a simple example, and the real process of cooking Palak Paneer is a lot more enjoyable! 🍽️ 💖