Basic JavaScript Best Practices

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.

Having the Correct for Loop Direction

We should make sure that we update the index variable in the right direction so that we don't get infinite loops.

For instance, the following is probably wrong:

for (var i = 0; i < 10; i--) {
}
Enter fullscreen mode Exit fullscreen mode

The loop never ends since i is being decremented in each iteration.

Instead, we should write:

for (var i = 0; i < 10; i++) {
}
Enter fullscreen mode Exit fullscreen mode

so that the i variable gets to 10.

Return Statement should be Present in Property getters

If we define a getter, then we should return something.

Otherwise, the getter is useless.

For instance, instead of writing:

const obj = {
  get name() {

  }
};
Enter fullscreen mode Exit fullscreen mode

We write:

const obj = {
  get name() {
    return 'james'  
  }
};
Enter fullscreen mode Exit fullscreen mode

or:

 Object.defineProperty(person, "age", {
   get() {
     return 17;
   }
 });

Enter fullscreen mode Exit fullscreen mode

No async Function as a Promise Executor

We shouldn't have async functions in our Promise constructor.

This is because async functions already returns promises, so it's redundant.

For instance, we shouldn't write;

const result = new Promise(async (resolve, reject) => {
  resolve(await foo);
});
Enter fullscreen mode Exit fullscreen mode

or:

const foo = new Promise(async (resolve, reject) => {
  readFile('bar.txt', (err, result) => {
    if (err) {
      reject(err);
    } else {
      resolve(result);
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

It's completely redundant to have them.

Instead, we write:

const foo = new Promise((resolve, reject) => {
  readFile('bar.txt', (err, result) => {
    if (err) {
      reject(err);
    } else {
      resolve(result);
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

or:

const result = Promise.resolve(1);
Enter fullscreen mode Exit fullscreen mode

No await Inside Loops

We should move await outside of promises that can run in parallel.

So instead of writing:

copnst foo = async (things) => {
  const results = [];
  for (const thing of things) {
    results.push(await bar(thing));
  }
  return baz(results);
}
Enter fullscreen mode Exit fullscreen mode

We write:

const foo = async (things) => {
  const results = things.map(thing =>bar(thing));
  return baz(await Promise.all(results));
}
Enter fullscreen mode Exit fullscreen mode

We map the things entries to promises.

Then we use Promise.all to run all the promises in parallel.

No Comparison Against -0

Comparing against -0 won't work as intended.

Instead, we compare an expression with 0.

So instead of writing:

if (x === -0) {
  //...
}
Enter fullscreen mode Exit fullscreen mode

We write:

if (x === 0) {
  //...
}
Enter fullscreen mode Exit fullscreen mode

We can use Object.is to compare against -0:

if (Object.is(x, -0)) {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Object.is distinguishes between +0 and -0.

No Assignment Operators in Conditional Statements

Assinging things in operators is probably a mistake if we don't compare it against something.

For instance:

if (user.title = "employee") {
  //...
}
Enter fullscreen mode Exit fullscreen mode

isn't comparing user.title to 'employee'.

Instead, we write:

if (x === 0) {
   b = 1;
}
Enter fullscreen mode Exit fullscreen mode

to make sure we're comparing against an expression.

Remove console from Production Code

We shouldn't run console.log when our code goes to production.

Therefore, we should remove them.

It's good for debugging but we should remove them before we check in our code.

Conclusion

We should take note of some basic best practices when writing JavaScript code.

Don't use async and await with the Promise constructor.

Don't write infinite loops unintentionally.

And return things in getters.

Also, don't assign variables unintentionally in our if statements.

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