Optimizing Loop In JavaScript
Tags: javascript, programming, performance
Published: 2020-04-16 09:28:57

---
title: Optimizing Loop In JavaScript
published: true
cover_image: https://images.unsplash.com/photo-1527266237111-a4989d028b4b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80
description: If you've been writing code for a while you might've developed a level of empathy for your machine. "It shouldn't work much while running my code".
tags: JavaScript, Programming, Performance
---

If you've been writing code for a while you might've developed a level of empathy for your machine. "It shouldn't work much while running my code". Not speaking of hard core algorithm optimization. But yah, it surely feels bad when there's a loop inside another loop.

While writing JavaScript, there are many places we could optimize our code to run faster. 
Like -
  - take the hot code out of main thread
  - make async calls parallel with `Promise.all`
  - debounce or throttle certain functions
  - use CSS properties that will trigger less rendering cycles

...and such points go on.

One most obvious thing among them is Loop. Loops are scary.

But maybe in most cases, the loop isn't the reason for bad performance but you might want to avoid unnecessary iterations. Hence the blog post people !

> The target is actually any kind of repetition like - loop, recursion or whatever

In JavaScript there are many APIs to write loop. These days we mostly use `map`, `reduce`, `filter`, `forEach`. It feels really good to write them. Because they enforce functional approach and the code management is quite good as well. Some people hate `reduce` though ;) .

Let's jump to the points - how we can write better Loops ?

<p>&nbsp;</p>

### The Magic Words - `break`, `continue` and `return`

Let's look at this example - 

```javascript
for(let i = 0; i < arr.length; i++){

    // we have got our answer 
    break

    // we don't need to go further in this iteration
    continue

    // heavy calculation here
}
```

Do you see what's happening here ? Now in `forEach`, `map`, `filter` - they don't stop. They are going to run through all iterations until the last `index`. Break doesn't work.

So in such cases we should pick `for loop` instead of trying to be cool. While the classic `for loop` is perfectly fine, you might want to use a better looking API - `for of`.

```javascript
for (let val of arr){

    // we have got our answer 
    break

    // we don't need to go further in this iteration
    continue

    // heavy calculation here
}
```

Now the gotcha is - what if we need `index` inside this loop ? In `for of` there's no direct `index` support. But there's always a hack for almost everything.

```javascript
for (let [index, val] of Object.entries(arr)){

}
```

If the loop is inside a function, and we use `return` inside that loop, the whole function is going to return. 

```javascript
function doSomething(){

  for(let val of arr){

    // mission accomplished
    return

    // some heavy calculation going on here
  }

}
```

This can't be done in `forEach`, `map` or some other array looping functional method. Because they have their own `return`.

<p>&nbsp;</p>

### You Might Not Need Iteration 

Let's look at another example -

```javascript
let playerInfo = [
    {
        name: 'Messi',
        club: 'Barcelona'
    },

    {
        name: 'Ronaldo',
        club: 'Juventus'
    },

    {
        name: 'Neymar',
        club: 'PSG'
    }
]

// here we want to find Neymar's club from this array
console.log(playerInfo.find(player => player.name === 'Neymar').club)
```

For this we need to loop over each element and see if it's Neymar and then get the club's value.

Sometimes a hashing/ dictionary approach would be better. Because then we don't need to iterate again and again. Just access the value directly.

```javascript
const playerInfo = {
  Messi: 'Barcelona',
  Ronaldo: 'Juventus',
  Neymar: 'PSG'
}

console.log(playerInfo.Neymar)
```

Maybe it's not the best example, but I am pretty sure you'd find better use case for this approach.

In some cases, this kind of `object` approach can save you from `O(N^2)` complexity.

```javascript
// let's find out if there's any repetition in this array
let arr = [1, 2, 3, 1] // 1 appears twice, so there's repetition

// loop on every item
// on another inner loop check -
// if this item has appeared in any other index
// so that would be O(N^2) solution


// Or,
// hash the value on one loop
let obj = {}
arr.forEach((v,i) => obj[v] ? obj[v]++ : obj[v] = 1)

// and on another loop check if some key has more than 1 value
// that would be of O(N+N) complexity and that's better
```

For some cases, you might consider a math equation instead of loop. Like - find out the summation of an explicit sequence.

```javascript
let arr = [1, 2, 3, 4, 5]

// which is better in this case ?

// this ?
let total = arr.reduce((currentVal, reducedVal) => currentVal + reducedVal , 0)

// or this ?
let n = 5 // last element - arr[arr.length - 1]
let sum = (n * (n+1)) / 2


// another dumb example
// which is better here ?
let arr = [2, 2, 2, 2, 2, 2]

// this ?
let total = eval(arr.join('+')) // eval ? really ??

// or this ?
let sum = 2 * arr.length 
```
<p>&nbsp;</p>

### Use the Correct Array Method for Particular Scenario

There are varieties of built in array methods available in JavaScript. Some are similar but each one has it's own purpose. It's better to think twice before applying `map` or `filter` for all use cases. 

For example - `find` vs `filter`

`find` is a better suit if we are looking for only one item. And `find` stops iterating after the desired value is found. `filter` would iterate until the last index as it's looking for all the matches.

There are other same [cases](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).

<p>&nbsp;</p>
### Memoization

Sometimes there could be same function calls with same parameters, in those cases we can save the value on first execution. Instead of running the function again, we could just use that saved value. This process is called memoization.

Just to give a rough idea - a silly example - look for better examples on the internet.

```javascript
let cache = {}
​
function plus(x){
  // there might be heavy calculation here
  console.log('i am here') // LOL
  return x + 2
}
​
function memoizedPlus(a){
  if(cache[a]){
    return cache[a]
  }
  
  else{
    cache[a] = plus(a)
    return cache[a]
  }
}
​
// run this code in your console and see what happens​

console.log(memoizedPlus(5))
console.log(memoizedPlus(1))
console.log(memoizedPlus(5))
console.log(memoizedPlus(3))
console.log(memoizedPlus(3))
```

I had a plan to talk about handling async operation inside loop. Maybe in another article. So for now that's all folks ! Stay safe and have fun.

![Loop](https://media.giphy.com/media/ieaUdBJJC19uw/giphy.gif)