Categories
JavaScript Best Practices

JavaScript Best Practices — Comparison and Old Constructs

Spread the love

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at some best practices when writing JavaScript code, including comparisons, accessors, objects, and loops.

=== and !== are Better Than == and !=

=== and !== saves us a lot of trouble from JavaScript type coercion. The algorithm for comparison using == and != because of it.

With == we get results like:

  • [] == false
  • [] == ![]
  • 2 == "02"

all of which return true .

There’s a lot list of rules that we have to aware of listed at https://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3 for == and != .

Therefore to avoid remembering all that and avoid weird results like the ones that are listed above, we should use === and !== for comparison.

So, we should avoid writing the following code:

if (x == 1) {

}

and instead, write:

if (x === 1) {

}

Other examples of good code include:

a === b
foo === true
apple !== 1
value === undefined
typeof foo === 'undefined'
'foo' !== 'bar'

Grouping Accessor Pairs in Object Literals and Classes

Grouping getters and setters for the same field together makes sense. It’s easier to read and we won’t have to search for them all over the code.

For instance, instead of writing:

const obj = {
  get a() {
    return this.val;
  },

  b: 1,

  set a(val) {
    this.val = val;
  }
}

and:

class Foo {
  get a() {
    return this.val;
  }

  b() {
    return 1;
  }

  set a(val) {
    this.val = val;
  }
}

We should instead write:

const obj = {
  get a() {
    return this.val;
  },

  set a(val) {
    this.val = val;
  },

  b: 1,
}

and:

class Foo {
  get a() {
    return this.val;
  }

  set a(val) {
    this.val = val;
  }

  b() {
    return 1;
  }
}

Checking for Own Properties in for…in Loops

for...in loop loops through an object’s own properties and also the properties up the prototype chain.

This will lead to unexpected items being looped through within the loop.

To avoid this, we should add a check to see if we’re looping through an object’s own properties so that we don’t accidentally loop through an object’s prototype’s properties.

Therefore, instead of writing:

for (const key in foo) {
  console.log(foo[key]);
}

We should write the following code instead:

for (const key in foo) {
  if (Object.prototype.hasOwnProperty.call(foo, key)) {
    console.log(foo[key]);
  }
}

The following code is also good:

for (const key in foo) {
  if ({}.hasOwnProperty.call(foo, key)) {
    console.log(foo[key]);
  }
}

In both examples, we called hasOwnPropterty with the call method to change the this value in hasOwnProperty to foo and pass in the key as the first argument to hasOwnProperty so that we can check if the key is in foo itself.

Don’t Have Too Many Classes Per File

Having too many classes per file makes it harder and read and navigate. The structure is also worse.

It’s best to limit each code file to a single responsibility. For instance, instead of writing in one file:

class Foo {}
class Bar {}

We should split them into 2 files:

foo.js :

class Foo {}

bar.js :

class Bar {}

Photo by Syed Ahmad on Unsplash

Disallow Use of Alert

JavaScript’s alert , confirm , and prompt functions are obtrusive as UI elements and should be replaced with modals, dialogs, or something else that’s less obtrusive.

It’s also often used for debugging code. Therefore, we should avoid using them unless we’re actually using them for alerting users and asking questions.

Even then, they should be used sparingly.

Stop Using arguments.caller and arguments.callee

arguments.caller and arguments.callee makes some code optimizations impossible. They’re also forbidden in strict mode.

They also don’t work in arrow functions since they don’t bind to arguments .

Therefore, we should either use arrow functions if we don’t need to bind to this . If we need to use traditional functions, then we shouldn’t reference those 2 properties in our function.

So:

function foo() {
  var callee = arguments.callee;
}

or:

function foo() {
  var caller = arguments.caller;
}

would be bad code that we want to avoid.

The alternative would be to reference the caller and callee functions directly. So arguments.callee would be foo .

Conclusion

We should use === and !== for comparison to avoid the confusing outcomes of the == and != comparison operators.

If we use accessors, then we should group the same value accessors together.

Also, maximum classes per file should be limited. The fewer the better. This limits any code file to a single responsibility.

Alerts, confirmation, and prompt pop-ups should be used as sparingly as possible.

Finally, we shouldn’t use arguments.caller and arguments.callee in traditional functions.

Leave a Reply

Your email address will not be published.

If you like the content of this blog, subscribe to my email list to get exclusive articles not available to anyone else.