Categories
JavaScript Best Practices

Better JavaScript — Coercion and Chaining

Spread the love

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at ways to improve our JavaScript code.

No Excessive Coercion

There should be no excessive data type coercion in our app.

JavaScript is very loose with types, so it coerces data types all the time.

Coercion may be convenient, but it’s easy to produce unexpected results since the rules are hard to remember.

Coercion is confusing when we work with overloaded function signatures.

So if we have:

function foo(x) {
  x = Number(x);
  if (typeof x === "number") {
    //...
  } else {
    //...
  }
};

We converted x to a number before running the rest of the code, so the type of x is always a number.

The else block will never be executed before of the coercion.

If we overload a function by checking the type of the parameter, then we shouldn’t coerce the data type.

Otherwise, we remove the if-else blocks since we don’t need them.

Instead, we can write:

function foo(x) {
  if (typeof x === "number") {
    //...
  } else if (typeof x === "object" && x !== null) {
    //...
  }
};

to check the data type of x for the types before running the code inside the blocks.

We can add type guards with a function.

For instance, we can write:

const guard = {
  guard(x) {
    if (!this.test(x)) {
      throw new TypeError("unexpected type");
    }
  }
};

We check the type with some test method.

When that returns false , we throw an error.

Other objects can use the guard object as its prototype and implement the test method themselves to do the type check.

To create an object with the given prototype, we can call Object.create on it:

const obj = Object.create(guard);

Support Method Chaining

Method chaining makes doing multiple operations in one statement easy.

For instance, with a string, we can call replace multiple times:

str.replace(/&/g, "&")
   .replace(/</g, "&lt;")
   .replace(/>/g, "&gt;")

This is because replace returns a string with the replacements done.

Eliminating temporary variables make it easier to read the code because there’s less distraction.

We can do this with our own methods by returning this .

For instance, we can write:

class Element {
  setBackgroundColor(color) {
    //...
    return this;
  }

  setColor(color) {
    //...
    return this;
  }

  setFontWeight(fontweight) {
    //...
    return this;
  }
}

to create a class with methods that return an instance of itself.

This way, we can chain each method and get the latest result.

For instance, we can use it by writing:

const element = new Element();
element.setBackgroundColor("blue")
  .setColor("green")
  .setFontWeight("bold");

This makes our lives easier since we don’t need any intermediate variables to get to the final result.

Other popular methods that let us change methods include some array methods and jQuery methods.

Conclusion

We shouldn’t coerce data types when we don’t need to.

Also, making methods chainable is also easier for everyone.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *