Loop Heuristics in Javascript

Different ways of looping in JS and my personal preferences to avoid complexity and errors.

Published in ·

We usually "loop" through lists of data in order to perform actions upon each element in the list (e.g., transform each element, print each element, search for a matching element, etc.). In Javascript, it is honestly a very rare context in which you want to "loop" when you do not have a list or collection to loop through.

Heuristic Advice

In general, prefer iterator functions, or for loops.

My Preferrences (in order of preference)

Increased Risk

Avoid Mutating Data

It is generally a better practice to choose a computing method which eliminates (or at least minimizes) mutating data. Mutating data is difficult to reason about. This increases the risk of errors, ability to scale/extend/change the code, and contributes to technical debt over time.

So, for example, in the case of loops, rather than mixing scopes and mutating variables like this:

const values = [1, 2, 3, 4, 5]
let changedValues = []

for (val of values) {
changedValues.push(val + 1)
}

console.log(changedValues)

or this:

const values = [1, 2, 3, 4, 5]

for (const i; i < values.length; i++) {
values[i] = values[i] + 1
}

console.log(values)

instead, try this:

const values = [1, 2, 3, 4, 5]
const changedValues = values.map(val => val + 1)

console.log(changedValues)

This way, changedValues is only ever assigned a value once, and doesn't change after that. You are guaranteed that by the time you print it out that it is what you expect it to be.

What happens when you mutate elements is that you open up the possibility that the value could change somewhere else in the code, making it more difficult to think about what value will be printed out:

const values = [1, 2, 3, 4, 5]
let changedValues = []

for (val of values) {
changedValues.push(val + 1)
}

// ...many more lines of code might get added here

if (someCondition) {
changedValues = ['new', 'values', 'here']
}

// ...many more lines of code might get added here

console.log(changedValues) // it's not obvious what values get used here

References