Rethinking JavaScript: Death of the For Loop Two days ago, I organized an introduction to JavaScript functional programming. I personally do not like complete functional programming, and there may be some problems in complex logic processing and performance. However, it is good to use the idea of functional programming to transform part of the code piece to improve its readability and testability. This article starts with for-loop, and I think it is very good.

For loops are heavily influenced by mutable states and side effects, but functional programming considers mutable states and side effects to be the culprits of potential error and unpredictability, a pattern to be avoided at all costs. It is well known that using global state can pollute local code, and the same local state can cause the same problems as global state, but because the influence of local state is limited to a small area of influence, it is not as abrupt as global state. Allowing mutable state means that variables can be changed for unknown reasons, and developers can spend hours trying to figure out which piece of code changed the value of a variable. In the past development years, I became bald because of this, but did not seem to get stronger. On the other hand, any function that modifies the values of variables other than those in scope is said to have side effects. Typical examples are modifying global variables, reading keyboard input, calling remote apis, writing to disk, and so on. Side effects are powerful and should be encapsulated and controlled as much as possible. With that said, let’s look directly at the code:

const cats = [ { name: 'Mojo', months: 84 }, { name: 'Mao-Mao', months: 34 }, { name: 'Waffles', months: 4 }, { name: 'Pickles', months: 6}] var kittens = [] i < cats.length; i++) { if (cats[i].months < 7) { kittens.push(cats[i].name) } } console.log(kittens)Copy the code

The first step in our transformation was to extract the logical judgment from the if statement, which I honestly found to be consistent with Clean JavaScript: The effect of writing a variable name in Clean JavaScript code instead of a comment:

const isKitten = cat => cat.months < 7
var kittens = []
for (var i = 0; i < cats.length; i++) {
  if (isKitten(cats[i])) {
    kittens.push(cats[i].name)
  }
}
Copy the code

This approach increases the usability of the code on the one hand, and also ensures the testability of our test conditions, especially when our logical judgments are complex. Here we extract and abstract the attribute:

const isKitten = cat => cat.months < 7
const getName = cat => cat.name
var kittens = []
for (var i = 0; i < cats.length; i++) {
  if (isKitten(cats[i])) {
    kittens.push(getName(cats[i]))
  }
}
Copy the code

We can describe this process using the filter and transform functions in the function below:

const isKitten = cat => cat.months < 7
const getName = cat => cat.name
const kittens =
  cats.filter(isKitten)
      .map(getName)
Copy the code

Here we get rid of the push function, which removes mutable state involvement. The final refactoring is to encapsulate our filtering and transformation process into a reusable process:





const isKitten = cat => cat.months < 7
const getName = cat => cat.name
const getKittenNames = cats =>
  cats.filter(isKitten)
      .map(getName)
const cats = [
  { name: 'Mojo',    months: 84 },
  { name: 'Mao-Mao', months: 34 },
  { name: 'Waffles', months: 4 },
  { name: 'Pickles', months: 6 }
]
const kittens = getKittenNames(cats)
console.log(kittens)
Copy the code