JavaScript Best Practices — Modules and Identifiers

John Au-Yeung - Jan 26 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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.

Minimum and Maximum Identifier Lengths

We should make identifier descriptive so they definitely shouldn’t be too short.

It also shouldn't be too long.

If it’s too short, it’s probably not descriptive enough.

If it’s too long, then it has redundant information and takes up too much space.

So we shouldn’t write:

const x = 5;
Enter fullscreen mode Exit fullscreen mode

since we don’t know what x is.

But we can write something like const numApples = 1; .

Location of Arrow Function Bodies with Implicit Returns

We should put arrows in a logical location.

For instance, we can write:

(foo) => bar;
Enter fullscreen mode Exit fullscreen mode

or

(foo) => (bar);
Enter fullscreen mode Exit fullscreen mode

or

(foo) => bar => baz;
Enter fullscreen mode Exit fullscreen mode

They are conventional and logical.

It’s better than these examples:

(foo) =>  
  bar;
Enter fullscreen mode Exit fullscreen mode

or:

(foo) =>  
  (bar);
Enter fullscreen mode Exit fullscreen mode

The first examples are more compact than these ones.

Default Imports

We’ve have a default export for a default import to work.

For instance, we should write:

foo.js

export default function () { return 100 }
Enter fullscreen mode Exit fullscreen mode

Then we should import it by writing:

import foo from './foo';
Enter fullscreen mode Exit fullscreen mode

For CommonJS modules, we can write:

foo.js

module.exports = function () { return 100 }
Enter fullscreen mode Exit fullscreen mode

Then we can import it by writing:

const foo = require('./foo');
Enter fullscreen mode Exit fullscreen mode

Repeated Imports and Exports

We can only have one default export in each module.

For instance, we can’t write:

export default class Foo { /*...*/ } 
export default class Bar { /*...*/ }
Enter fullscreen mode Exit fullscreen mode

We have to remove one of them.

If we remove one:

export default class Foo { /*...*/ }
Enter fullscreen mode Exit fullscreen mode

Then we can write:

import Foo from './foo';
Enter fullscreen mode Exit fullscreen mode

Export Statements that Come Before Other Statements

We shouldn't have export statements that come before other statements.

For instance, we don’t want to fix statements like:

const bool = true
export default bool
const str = 'foo'
Enter fullscreen mode Exit fullscreen mode

Moving all exports to the bottom would make it easier to read.

Use of File Extension within the Import Path

When we write imports, we don’t need an extension for JavaScript files.

For instance, instead of writing:

import bar from './foo/bar.js';
Enter fullscreen mode Exit fullscreen mode

We write:

import bar from './foo/bar';
Enter fullscreen mode Exit fullscreen mode

However, we should put the extension for JSON import.

For instance, we can write:

import bar from './bar.json';
Enter fullscreen mode Exit fullscreen mode

We may also do the same thing for JavaScript files that don’t have the .js extension.

For instance, we can write:

import Component from './Component.jsx';
Enter fullscreen mode Exit fullscreen mode

for JSX files.

Putting Imports First

We should put import statements first.

For instance, we should put them at the top.

Instead of writing:

import foo from './foo'
doSomething(foo)
import bar from './bar'
Enter fullscreen mode Exit fullscreen mode

We write:

import foo from './foo';  
import bar from './bar';
doSomething(foo);
Enter fullscreen mode Exit fullscreen mode

Grouping Exports

We can group exports together to make finding them easier.

For instance, we can write:

const first = 'foo';  
const second = 'bar';
export {  
  first,  
  second,  
}
Enter fullscreen mode Exit fullscreen mode

With CommonJS modules, we can write:

const test = {};  
test.foo = true  
test.bar  = true
module.exports = test;
Enter fullscreen mode Exit fullscreen mode

We also grouped the exports together.

Named Exports

We can import named module members in various ways.

Given that we have:

export const foo = "foo"
Enter fullscreen mode Exit fullscreen mode

We can write:

import { foo } from './foo'
Enter fullscreen mode Exit fullscreen mode

Also, we can write:

export { foo as bar } from './foo'
Enter fullscreen mode Exit fullscreen mode

to export it as bar .

We can also import it as bar:

import { foo as bar } from './foo'
Enter fullscreen mode Exit fullscreen mode

Newline After Import

After a group of imports, we can put a new line to separate the imports from the rest of the code.

For instance, we can write:

import defaultExport from './foo'  
import { bar } from 'bar'  

const foo = 'bar';
Enter fullscreen mode Exit fullscreen mode

or:

const foo = require('./foo')  
const bar = require('./bar')  

const baz = 1;
Enter fullscreen mode Exit fullscreen mode

for CommonJS modules.

No Absolute Paths

We shouldn’t use absolute paths for imports because it’ll only work on the current computer’s current folder strucutre.

If we move it anywhere, it won’t work.

So we shouldn’t write:

import f from '/foo';  
import bar from '/some/path';
Enter fullscreen mode Exit fullscreen mode

or:

const f = require('/foo');  
const bar = require('/some/path');
Enter fullscreen mode Exit fullscreen mode

Instead, we write:

import f from './foo';  
import bar from './some/path';
Enter fullscreen mode Exit fullscreen mode

or:

const f = require('./foo');  
const bar = require('./some/path');
Enter fullscreen mode Exit fullscreen mode

Conclusion

We should write our imports and exports properly.

Never import with absolute paths.

And we should group them together.

Identifier lengths shouldn’t be too long or short.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .