Great programmers write code for humans, not for computers. A good rule of thumb to follow it to treat your codebase as if the next person to take over the project is a madman who knows where you live. If that were true, you’d surely want to be meticulously concise and write high-quality code.
1. Use .map or .forEach instead of for Loops
Every complex application requires a decent amount of looping over sets of data, usually in the case of arrays or objects. With
for loops, code becomes quickly unreadable and hard to follow.
For example, take a look at the code below and tell me which one you would prefer.
The code above loops over the array of numbers and prints each number to the console.
But what if we have more complex arrays, like an array of objects? Use
reduce for iteration purposes.
Finally, here’s what’s being printed to the console. The result is the same, but the code is much cleaner with the functional programming approach.
The only exception to using
for loops is when we iterate over objects. That’s because
filter are methods we can call on for arrays only.
In the case of looping over objects, we could use
A better approach to iterate over objects would be to use the following methods:
Object.keys— returns an array of a given object’s own enumerable property names, iterated in the same order as that provided by a normal loop
Object.values— returns an array of a given object’s own enumerable property values, in the same order as that provided by a
Object.entries— returns an array of a given object’s own enumerable string-keyed property
[key, value]pairs, in the same order as that provided by a
The above methods grab the keys or values from the object, place them into an array, and return the array as a result.
Now that we have an array, we can iterate the values, with
forEach to grab the values.
Here are a couple of different approaches to iterating over objects with different goals in mind.
2. Use const by Default
The difference between
let is simple.
const is immutable and
let allows us to reassign variables.
const by default, there’s less of a cognitive load since we don’t have to chase and guess what each variable stands for. Use
let whenever we mutate variables.
Take the example below. We might have declared our name earlier and mutated it multiple times. We might run into some unexpected bugs that could have been avoided with using
The arguments in favor of using
const by default are the following:
- It avoids side effects caused by involuntary reassignments.
- It provides a better developer experience because it removes uncertainty. The developer who sees a
constvariable can count on it not being reassigned.
constis more consistent with functional programming and immutable states.
3. Avoid Nesting Closures
Did you find the closure? Here’s a hint: The closure is located on line 4. Remember, a closure captures variables from the outside function.
Now that we’ve established what a closure is, the question is how can we improve the code. It’s a relatively simple piece of code that formats all the names inside the array to lowercase.
Hint: Avoid nesting closures.
Here’s a simple example of one way you could avoid nesting closures.
Notice we took the closure and placed it inside a function expression. This way our code is much easier to follow and reason with. Take the following code example.
The code above iterates over the array of objects, and then it sums the scores and rounds to a round number. While it’s understandable, we can still improve the code. There’s always room for improvement.
Here’s how you can improve the code by simply extracting the score-summing logic to its own function expression.
4. Avoid Nested ifs
if statements are by far the biggest code smell. Nesting if statements is a slippery slope to an unmaintainable codebase. Do yourself and your team a favor and avoid nesting
Here’s what a naive approach looks like when checking conditions by nesting
Take a moment to think about how you would improve this code. Here’s what I’ve come up with.
We went from seven lines of code to three. That’s a huge improvement. Since all three conditions must be evaluated to
true, we can use the
&& operator. The
&& stands for
and. Another alternative is to use the double pipe operator
||, which stands for
or. The difference between
|| is that all
&& conditions must be met, but with
||, only one condition must be met to execute the
5. Use Variables Instead of Complicated if Clauses;
There might be a time when we find ourselves in a situation where we have multiple complicated
if statements. Take a peek at the verbose code below.
The cognitive load generated by such code is large. I strongly advocate for the best possible developer experience. How would you improve the code? Here’s what I came up with.
By placing the comparisons into separate variables, the code is much easier to follow and reason with. It takes a couple of seconds extra, but by leveraging best practices all over the codebase, we improve developer productivity in the long run.
Thanks for reading, and I hope you found this article useful. Treat your code as art. You want to express yourself as clearly as possible — leave no room for misinterpretations. Happy coding!