Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices we should follow when writing JavaScript code.
Don’t Use Logical Operators as Statements
We shouldn’t write clever but hard to read code.
For example, something like:
a() || b.foo.bar(); m && c() ? d() : l || m.baz[bee](3);
is impossible to read.
And therefore this should be avoided.
Always Declaring Variables at the Top of Their Scope
We can put variables at the top of their scope:
function calculate() {
let width, height, length;
// ...
}
This way, they’re easy to see and we can work with them anywhere.
Repeatedly Used Inline Object Literals
If we have object literals that are repeatedly used with some variation, we can put them in a function.
For example, we can write:
function prepareRequest(mode, updateId, value) {
const req = {
mode,
updateId,
value,
uid: genUID()
};
//...
}
This way, we can call prepareRequest
and use it anywhere.
Complex Inline Regex
Complex inline regex is impossible to read.
For example, if we have:
if (/^((\[^<>()[]\.,;:\s@"\]+(\.\[^<>()[]\.,;:\s@"\]+)\*)|(".+"))@(([\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\])|((\[a-zA-Z\-0-9\]+\.)+\[a-zA-Z\]{2,}))$/.test(str)) {
// ...
}
We have no idea what it’s checking.
Instead, we can assign it to variable and then use it like:
const emailRegex = /^((\[^<>()[]\.,;:\s@"\]+(\.\[^<>()[]\.,;:\s@"\]+)\*)|(".+"))@(([\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\.\[0-9\]{1,3}\])|((\[a-zA-Z\-0-9\]+\.)+\[a-zA-Z\]{2,}))$/
if (emailRegex.test(str)) {
// ...
}
Now we know the regex is actually used for checking for a valid email address.
Strict Equality Everywhere
Strict equality just helps us with avoiding issues with automatic data type coercion.
The rules for data type conversion is complex with the ==
or !=
operators.
So we should instead use the ===
and !==
operators to check for equality and inequality respectively.
For example, we can write:
if (typeof x === 'string' && x === 'abc') {
// ...
}
to compare their type and value.
Assuming Truthiness Equals Presence
We shouldn’t assume truthiness means something ins present in an object.
To check if a key is in an object, we should use hasOwnProperty
or the in
operator.
Instead of writing:
if (!cache[key]) {
cache[key] = value;
}
We should write:
if (!cache.hasOwnProperty(key)) {
cache[key] = value;
}
or:
if (!(key in cache)) {
cache[key] = value;
}
The in
operator also checks the prototype for a property.
Commenting Nothing or Commenting Every Little Thing
No comments and commenting on everything are both bad.
Sometimes there are things that need an explanation that isn’t in the code.
However, it’s also bad to make comments on things that are already covered by the code.
Write Something Reliable without Unit Tests
It’s just hard to write something reliable without unit tests.
They definitely give us peace of mind when we’re changing code.
Using Long Names and Being Overly Specific
We shouldn’t have names that are too long and are overly specific.
Names like:
function generateNewtIDForANewRequestCacheItem() {...}
function deleteRequestCacheItemsThatDoNotEqual(value) {...}
They are definitely too long and too specific.
We should definitely find ways to reduce the length of them.
They have lots of extra information we don’t need.
Conclusion
We should take note of some practices to make our code easier to read.
We may go overboard with some good practices as well.