To make code easy to read and maintain, we should follow some best practices.
In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.
Remove Duplicate Code
Duplicate code is bad.
If we have to change them, we’ve to change them in multiple places.
It’s easy to miss them.
Therefore, we should remove them.
For instance, instead of writing:
function showEmployeeList(employees) {
employees.forEach(employee => {
const salaries = employees.salaries();
const tasks = employees.tasks();
const data = {
salaries,
tasks
};
display(data);
});
}
function showManagerList(managers) {
managers.forEach(manager => {
const salaries = manager.salaries();
const tasks = manager.tasks();
const data = {
salaries,
tasks
};
display(data);
});
}
We write:
function showWorkersList(workers) {
workers.forEach(worker => {
const salaries = worker.salaries();
const tasks = worker.tasks();
const data = {
salaries,
tasks
};
switch (worker.type) {
case "manager":
render(data);
case "employee":
render(data);
}
});
}
Set Default Objects with Object.assign
Setting a non-empty object as the first argument of Object.assign
will return an object with all the properties of the object in the first argument merged with the ones with the other arguments.
For instance, we can write:
const obj = Object.assign({
title: "Foo"
},
config
);
obj
is an object with the title
with the properties in config
after it.
Don’t Use Flags as Function Parameters
We shouldn’t use flags as function parameters.
For instance, we can write:
function getData(name, isManager) {
if (isManager) {
return findManagerData(name);
} else {
return findWorkerData(name);
}
}
We write:
function getManagerData(name) {
return findtManagerData(name);
}
function getWorkerData(name) {
return findtWorkerData(name);
}
No Side Effects
Side effects are something that’s done to something outside the function
Some side effects are unavoidable, like manipulating files and changing other external resources.
Most of the rest can be avoided.
For instance, we shouldn’t write:
let name = "foo bar";
function splitName() {
name = name.split(" ");
}
since we can return the result in a function instead.
We can instead write:
function splitName(name) {
return name.split(" ");
}
Don’t Manipulate Objects in Place if it’s Passed from a Function Parameter
All non-primitive values, including objects and arrays, are passed into a function by reference.
Therefore, if we modify these parameters, then we’ll change the original object.
For instance, if we have:
const addTask = (tasks, task) => {
tasks.push(task);
};
Then the tasks
array and the task object
that’s passed in will be modified.
Therefore, we should return a new array instead:
const addTask = (tasks, task) => {
return [...tasks, tasks];
};
This is a more hidden side effect that we may not have thought of.
Don’t Write to Global Functions
Never modify built-in prototypes.
Instead, we can extend them.
Extending built-in prototypes think unexpected results.
They make testing easier and prevent bugs from mutating data.
For instance, instead of writing:
Array.prototype.itemsInOtherArray = function(arr) {
return this.filter(element => !arr.includes(element));
};
We write:
class DiffArray extends Array {
itemsInOtherArray(arr) {
return this.filter(element => !arr.includes(element));
}
}
Use Functional Programming
We should use functional programming principles like not committing side effects.
Also, we make objects immutable.
Higher-order functions are also something we can use.
Some array methods are perfect examples of something that exhibit all these characteristics.
Instead of computing sums with a loop:
let totalPrice = 0;
for (const item of items) {
totalPrice += item.price;
}
We write:
const totalPrice = items.reduce(
(totalPrice, output) => totalPrice + item.price,
0
);
JavaScript arrays have the reduce
method to add the total price from the array entries.
Encapsulate Conditionals
If we have long boolean expressions in conditional, we can put them in a function.
For instance, instead of writing:
if (item.price > 100 && isLarge(item) && isSmart(item)) {
// ...
}
We can write:
const isBigAndSmart = (item) => {
return item.price > 100 && isLarge(item) && isSmart(item)
}
if (isBigAndSmart(item)) {
// ...
}
No Negative Conditionals
We shouldn’t have negative conditional in our code.
They are hard to read.
For example, instead of writing:
if (!isPresent(node)) {
// ...
}
We write:
if (isPresent(node)) {
// ...
}
Conclusion
We should take advantage of functional programming features in JavaScript.
Also, we should remove duplicate code and move complex code into their own function.