JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to write a piece of clean JavaScript code.
In this article, we’ll look at some easy things that can be refactored without much effort even with the ugliest code.
No Invariant Functions
Invariant functions are ones that always return the same thing given any kind of input.
Obviously, that’s pretty useless since it’s the function that always returns the same thing.
With invariant functions, either we should just assign the returned value as a constant, or change the function to return something different given different kinds of outputs.
For instance, if we have the following function:
const foo = name => 'name';
Then this should be refactored because the function always returns 'name'
. We don’t want a function like that because the parameter is useless and the return value is constant.
A function that commits a side effect but always returns the same thing is also an invariant function.
For instance, if we have:
let name;
const setName = (firstName, lastName) => {
name = `${firstName}, ${lastName}`;
return 'name';
}
Then that’s also an invariant function since it returns the same thing. What it does before that doesn’t matter.
In this example, we should refactor our function so that it becomes a pure function.
For instance, we should rewrite the setName
function to be a pure function and call it as follows:
const setName = (firstName, lastName) => `${firstName}, ${lastName}`
In the code above, we changed the setName
function to a pure function by changing it to return the firstName
and lastName
parameters combined.
Now we don’t have an invariant function anymore since it doesn’t always return the same thing.
Also, now we can call it as follows:
let name = setName('jane', 'smith');
This is better than committing side effects unnecessarily.
Pure functions are easy to test and understand since the output is predictable given the input.
Keep the Default Clause of a switch Statement Last
The default
clause of a switch
statement should be last to following commonly accepted convention. This makes our code easier to read since it’s consistent and the pattern is predictable. Thus reducing the cognitive load on the reader.
Therefore, instead of writing:
const foo = (bar) => {
switch (bar) {
default: {
return 1
}
case 'foo': {
return 2
}
case 'bar': {
return 3;
}
}
}
We should instead write:
const foo = (bar) => {
switch (bar) {
case 'foo': {
return 2;
}
case 'bar': {
return 3;
}
default: {
return 1;
}
}
}
This is much easier to read for anyone as we stick to conventions that are accepted by most people.
Clean up Redundant Variables
Redundant variables are hard on our brains. Also, they take up more memory on the user’s computer as the browser or Node.js has to allocate more resources or each variable.
The cluttering of the code makes it hard to read and debug since they’re misleading. They look different but they actually are used for the same thing.
For instance, instead of writing:
const foo = (bar) => {
switch (bar) {
case 'foo': {
const two = 2;
return two * 2;
}
case 'bar': {
const three = 3;
return three * 2;
}
default: {
const one = 3;
return one * 2;
}
}
}
which has 3 constants that we don’t need. We can instead write:
const foo = (bar) => {
let num;
switch (bar) {
case 'foo': {
num = 2;
return num * 2;
}
case 'bar': {
num = 3;
return num * 2;
}
default: {
num = 3;
return num * 2;
}
}
}
In the code above, we have the num
variable, which are assigned in each case
block and also the default
block.
Then we can use the num
variable the way we wish to after setting it. Now we only have 1 variable instead of 3, saving computer memory and also reducing the cognitive load on the reader.
Conclusion
There’re a few quick wins when it comes to refactoring. One is to remove redundant variables.
We also shouldn’t move the default
block of a switch
statement outside of its normally accepted position from the bottom.
Finally, we shouldn’t write invariant functions, even if they commit side effects.