JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.
In this article, we’ll look at the best ways to work with classes and modules.
Add a toString Method
We can add a toString
method to our class if we want.
However, we should make sure that it doesn’t commit any side effects.
For instance, we can write:
class Person {
constructor(name) {
this.name = name;
}
toString() {
return `Person - ${this.getName()}`;
}
}
We have a toString
method to return the string representation of our class instance.
We can Skip the constructor Method if we Don’t Want to Put Anything in it
We don’t need to add an explicit constructor
method to a class.
For instance, instead of writing:
class Person {
constructor() {}
//...
}
We write:
class Person {
//...
}
They’re the same.
If we have a subclass, instead of writing:
class Waiter extends Person {
constructor(...args) {
super(...args);
}
//...
}
We write:
class Waiter extends Person {
//...
}
We don’t need a call to the parent constructor if we don’t do anything in the constructor that’s unique to the subclass.
No Duplicate Class Members
We shouldn’t declare duplicate class members.
This is because the value of the method will always be the last one.
If we have:
class Foo {
bar() {
return 1;
}
bar() {
return 3;
}
}
Then bar
returns 3.
So we should just stick with one:
class Foo {
bar() {
return 1;
}
}
2 or more members of the same name are redundant.
Class Methods Should use this or be Made into a Static Method
If our method doesn’t reference this
, then it should be static.
For instance, instead of writing:
class Foo {
bar() {
console.log('bar');
}
}
We should write:
class Foo {
static bar() {
console.log('bar');
}
}
Modules
Since ES6 has modules, it’s time to use them to organize our code.
Always Use Standard Modules
Before JavaScript has modules as a standard, there were various module systems.
However, now that JavaScript has modules as a standard feature, it’s time to ditch non-standard module systems.
For instance, instead of writing:
const foo = require('./foo');
and:
module.exports = {
foo: 'bar'
};
We should write:
import foo from './foo';
//...
export default bar;
or:
import { foo } from './foo';
//...
export default bar;
No Wildcard Imports
We shouldn’t use wildcard imports to import everything.
For instance instead of writing:
import * as foo from './foo';
We write:
import foo from './foo';
or:
import { bar } from './foo';
Don’t Export Directly from an Import
We shouldn’t use export
in the same line as we import.
It’s better to make the imports and exports clear and consistent.
For instance, instead of writing:
export { bar as default } from './foo';
to export bar
in the same line as we import bar
from foo
, we write:
import { bar } from './foo';
export default bar;
Import a Path only in one Place
We should have multiple lines that import members from the same module.
For instance, instead of writing:
import bar from 'foo';
import { baz, qux } from 'foo';
We should write:
import bar, { baz, qux } from 'foo';
Don’t Export Mutable Variables
We shouldn’t export anything that’s mutable. This is because the last value will be exported.
For instance, if we have:
foo.js
let bar = 3;
export { bar };
bar = 5;
Then when we import bar
:
import { bar } from "./foo";
console.log(bar);
bar
is 5.
Even though the export is done before bar
is set to 5, we still get that it’s 5 after we import.
Therefore, just export const
members:
foo.js
const bar = 3;
export { bar };
Conclusion
We should never export mutable variables. This way, they can’t change after we export them.
Also, we should separate import and export statements so that it’s clear what we’re doing.
If we don’t want to put anything in the constructor, we can skip it.