Loops versus Performance

In almost every programming language, loops are so simple and obvious that they are one of the first topics to be picked up while teaching that language — JavaScript being no exception. What if I told you that in many cases, you can simplify your code and speed up your UI by avoiding loops?

“Tell me more.”

Most UI libraries and frameworks today are built on a single core concept: data binding. Data binding means keeping your state in a JavaScript variable, and “binding” the DOM to it so that it reflects the contents of the variable. In simple words, your UI updates every time you change the contents of your variable.

The problem is, updating the UI is a costly operation. It involves creating, changing or removing DOM nodes, recalculating the positions of elements, and then repainting the pixels on the screen. You want to avoid triggering such changes unless absolutely necessary.

“How do I do that?”

Subjective question. However, there’s this one technique that advanced developers might take for granted, but is not commonly known to novice developers: avoid loops. More precisely, if you have an array that is data-bound to the UI, do not call things like push, pop, shift, unshift or splice on it, especially in a loop. An accurate rewording would be: avoid mutative loops.

For example, let’s say we are displaying a list of fruits in a ul.

<ul *ngFor="let fruit of fruits">
    <li>{{fruit}}</li>
</ul>

This is Angular, but it won’t be very different for other frameworks or libraries.

And let’s say we’re fetching the list of fruits and adding them to an array.

this.fruits = [];

let list = [{name: 'apple'}, {name: 'banana'}, {name: 'chickoo'}];

list.forEach(fruit => {
    this.fruits.push(fruit);
});

Here, when you call push on fruits, you trigger a UI update three times for a list of three fruits. Now imagine you have a hundred fruits.

“Oh my!”

Exactly. This is where map comes in.

map is a nice array method, which asks you for a function, and then runs that function for every element in the array. Then it gives you an array of all returned values.

Check this:

this.fruits = list.map(fruit => fruit.name);

Pretty simple, eh? You just wrote a function that takes a fruit and returns the value of its name property, and you passed this function to map. What you got is a list of fruit names.

Besides being simple and concise, this also ensures that the fruits array is assigned only once, and the DOM update is only called once. Remember all that tree-mangling and repainting? All of that happens in one go. Welcome to the fast lane.

You can find more details and examples of the map method here. If you like map, also take a look at its frequent companion filter. You can thank me later.

Happy coding,
Darshak

Leave a comment