Web Programming TutorialsMemoization in JavaScript

Memoization in JavaScript

Functions are fundamental parts of programming. JavaScript ecosystem, whether a frontend framework or library or, on the backend, use functions comprehensively. They improve and provide reusability of code in our JavaScript applications. You can break your code into modular functions and avoid repeating and writing business logic again and again for different use cases. The popularity of Nodejs and modern-day frontend library like ReactJS.

What is Memoization?

We are sure you must have come across a recursive function at least once in your life. For example, take a look at the function below which returns the factorial of a number. That said, it is recursive in nature.

const factorial = n => {
    if (n === 1) {
        return n;
    }
    return n * factorial(n - 1);
};

// factorial(4)
// 4! === 4 * 3 * 2 * 1 === 24

If you pass in factorial(4), the calculations would be made and return by the function above will result in the value 24, every time it runs. This nature can be elongated both in terms of writing code and time taken to execute. These types of functions can execute at a faster rate by using Memoization. For example, you want to calculate the factorial of number 778453. Imagine the computational resource and time taken by the recursive function above will be definitely more than executing factorial(4). Much more. However, to save time and computational resource, you can use the technique of Memoization.

Actually, memoization as a concept can be defined as:

Memoization is an optimization technique used primarily to speed up programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

The simplest explanation of the above definition is that a function that uses memoization technique to solve a problem for us, will memorize the solution for us if given the same input value. To achieve this, we need to implement some type of cache that the recursive function can refer to.

Using memoization technique, the factorial function can be re-written as:

const MemoizedFactorial = () => {
    const cache = {};
    return value => {
        if (value in cache) {
            // return the value from the cache
            return cache[value];
        } else {
            // calculate factorial of the value
            const result = factorial(value);
            cache[value] = result;
            return result;
        }
    };
};

The above function MemoizedFactorial returns a value which is being called at a later time, this making it recursive. The cache introduced by us, is a JavaScript object that will remember values. When you input a value into our memoized function such as above and assuming that input value has been used before, the function itself returns the value stored in the cache instead of running the function again. This boosts the performance and improves the executional time. No longer does the function have to recalculate every input value to get the desired result.

Practical use: Using Memoization in React

Let us consider a scenario where you are computing JSON data from a third party API that throws data structured as below:

[
    {
        "name": "Luke Skywalker",
        "height": "172",
        "birth_year": "19BBY",
        "gender": "male"
    }
    // also there more than 100 objects similarly structured
]

This array of data contains an object pointing towards one Star Wars character. You are going to use this JSON data in a ReactJS application. You are going to use this to provide search functionality in the React app. Let us create a component and see how we can implement this search box where a user can enter the query to search for specific Star Wars character.

import React from 'react';

class App extends React.Component {
    state = {
        searchValue: ''
    };

    filterList = (list, searchValue) =>
        list.filter(member => member.name.toLowerCase().startsWith(searchValue));

    sortList = list =>
        list.sort((a, b) => {
            if (a.name < b.name) return -1;
            if (a.name > b.name) return 1;
            return 0;
        });

    handleInputChange = searchValue => {
        this.setState({ searchValue, inputChanged: true });
    };

    render() {
        const { searchValue, inputChanged } = this.state;
        const filteredMembers = this.filterList(data, searchValue);
        const members = this.sortList(filteredMembers);

        return (
            <div className="App">
                <Search
                    searchValue={searchValue}
                    onInputChange={e => this.handleInputChange(e.target.value)}
                    placeholder="Search for a member"
                />
                <div className="members">
                    {members.map(member => {
                        return <Member member={member} key={member._id} />;
                    })}
                </div>
            </div>
        );
    }
}

This component won’t be throwing any performance issues in your way if the data set is small. But what if this third party API gets an update and the number of characters increases from 100 to 1000. Definitely, your application will be facing some issues when rendering and querying a large data set like that. Filtering large sets of data is an expansive computation operation but you cannot avoid in most situations. The optimum solution in this scenario is to use memoization.

With React you can use an npm package that allows you a React component to use Memoization technique. This npm package is called memoize-one which can be installed by running a command from your terminal: npm install -S memoize-one.

import React from 'react';
import memoize from 'memoize-one';

class App extends React.Component {
    state = {
        searchValue: ''
    };

    filterList = memoize((list, searchValue) =>
        list.filter(member => member.name.toLowerCase().startsWith(searchValue))
    );

    sortList = memoize(list =>
        list.sort((a, b) => {
            if (a.name < b.name) return -1;
            if (a.name > b.name) return 1;
            return 0;
        })
    );

    handleInputChange = searchValue => {
        this.setState({ searchValue });
    };

    render() {
        const { searchValue } = this.state;
        const filteredMembers = this.filterList(data.slice(0, 50), searchValue);
        const members = this.sortList(filteredMembers);

        return (
            <div className="App">
                <Search
                    searchValue={searchValue}
                    onInputChange={e => this.handleInputChange(e.target.value)}
                    placeholder="Search for a member"
                />
                <div className="members">
                    {members.map(member => {
                        return <Member member={member} key={member._id} />;
                    })}
                </div>
            </div>
        );
    }
}

In the meantime, if you are interested to learn World’s most popular and misunderstood programming language then you can explore the different sections of Advanced JavaScript for the Beginners Online Tutorial.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Exclusive content

- Advertisement -

Latest article

21,501FansLike
4,106FollowersFollow
106,000SubscribersSubscribe

More article

- Advertisement -