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.
No Assigning to Imported Bindings
We shouldn’t assign anything directly to imported bindings.
It’ll cause run time errors if we do since they’re read-only.
For instance, we shouldn’t write:
import mod, { named } from "./foo"
mod = 1;
named = 2;
Instead, we write:
import mod, { named } from "./foo"
const bar = 1;
const baz = 2;
No Inline Comments After Code
Inline comments after a line of code is a pain to write.
There also might be enough spaces to write them after a line.
For instance, if we have:
function getRandomNumber() {
return 4; // roll a dice
// It's a real dice.
}
We’ve to add lots of spaces in the 2nd line of the comment to make them align.
We can make our lives easier if we don’t make them inline:
function getRandomNumber() {
return 4;
// roll a dice
// It's a real dice.
}
No Variable or Function
Declarations in Nested Blocks
We shouldn’t have variables or function declarations in nested blocks.
It’s illegal syntax but it’s still allowed by JavaScript interpreters.
For instance, instead of writing:
if (foo) {
function doSomething() {}
}
We write:
function doSomething() {}
No Invalid Regular Expression strings in RegExp
Constructors
If we write a regex, then we should make sure we have a valid pattern inside.
For instance, we shouldn’t write:
RegExp('[')
RegExp('.', 'z')
Instead, we write:
RegExp('foo')
RegExp('d', 'g')
No this
Keywords Outside of Classes or Class-Like Objects
We shouldn’t have the this
keyword outside of classes or class-like objects.
They can only be used in those entities.
So instead of writing:
this.a = 0;
baz(() => this);
We write:
function Foo() {
this.a = 0;
baz(() => this);
}
class Bar {
constructor() {
this.a = 0;
baz(() => this);
}
}
Foo
is a constructor function and Bar
is a class, so we can use this
in there.
No Irregular Whitespace
We should make sure our whitespace characters are normal whitespace characters.
Most text editors can replace irregular ones with regular ones.
No Iterator
The __iterator__
property isn’t a standard property.
So we shouldn’t use it to create an iterator.
Instead, we use generators to create iterators:
function* generator() {
yield 1;
yield 2;
yield 3;
}
We have the generator
generator function.
Which we can create a generator from by writing:
const gen = generator();
No Labels That Are Variables Names
We shouldn’t have labels that are the same variable names.
This will cause confusion for most people.
For instance, we shouldn’t have code like:
let x = 'abc';
function bar() {
x: for (;;) {
break x;
}
}
We have x
as a variable and a label for a loop.
Instead, we write:
let x = 'abc';
function bar() {
z: for (;;) {
break z;
}
}
Or we just don’t use labels.
No Labeled Statements
Labeled statements lets us set a name for a loop so we can use break
or continue
with it.
However, it’s a rarely used feature and most people don’t know about it.
Therefore, we should just use something else.
For instance, instead of writing:
outer:
while (true) {
while (true) {
break outer;
}
}
We write:
while (true) {
break;
}
No Unnecessary Nested Blocks
We shouldn’t have unnecessary nested blocks.
For instance, the following isn’t useful:
{
var foo = baz();
}
It’s only useful for let
and const
variables, which are block-scoped.
So we write:
{
let foo = baz();
}
{
const foo = baz();
}
to keep foo
in their own blocks only.
No if
Statements as the Only Statement in else
Blocks
We shouldn’t have code like:
if (foo) {
// ...
} else {
if (bar) {
// ...
}
}
Because this is the same as:
if (foo) {
// ...
} else if (bar) {
// ...
}
It’s much shorter and it does the same thing.
Conclusion
We can’t reassign values to imported bindings.
Also, we should remove labels, redundant blocks, and redundant if
statements.
We also should make sure that regex has valid patterns in it.