Maintainable JavaScript — App Logic and Primitive Value Check

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/

Creating maintainable JavaScript code is important if want to keep using the code.

In this article, we’ll look at the basics of creating maintainable JavaScript code by looking at separating app logic from event handling.

Also, we look at how to check for primitive values.

Event Object

When we’re handling events, we should keep the event object in the event handler only.

This will reduce coupling in our code.

So if we need to use something from the event object, we keep them in the event handler.

For instance, we can write:

function onclick(event) {
  const {
    clientX,
    clienty,
    preventDefault,
    stopPropagation
  } = event;

  preventDefault();
  stopPropagation();
  showPopup(clientX, clienty);
}

function showPopup(x, y) {
  const popup = document.getElementById("popup");
  popup.style.left = `${x}px`;
  popup.style.top = `${y}px`;
  popup.className = "popup";
}

const button = document.querySelector('button');
button.addEventListener('click', onClick);
Enter fullscreen mode Exit fullscreen mode

We called the preventDefault and stopPropagation methods in from the event object in the event handler.

This is much better than passing the event object and call it in that function.

We don’t want our app logic code and event handling code to mix.

This way, we can change the app logic and event handling code independently.

And we can call the app logic code directly.

So we can write something like:

showPopup(10, 10);
Enter fullscreen mode Exit fullscreen mode

It also makes testing a lot easier since we can call showPopup directly to test it.

Avoid Null Comparisons

A common problematic pattern in JavaScript code is testing variables against null .

For instance, we may have code like:

function process(items) {
   if (items !== null) {
     items.sort();
     items.forEach((item) => {
       //...
     });
   }
 }
Enter fullscreen mode Exit fullscreen mode

We have the process function that checks the items against null .

Then we assume items is an array and call sort and forEach on it.

Comparing against null doesn’t mean we made sure that it’s an array.

We only know that it’s not null .

We can improve our value comparison so that we can actually check for what we want.

Detecting Primitive Values

There’re a few types of primitive values in JavaScript.

They include bigints, strings, numbers, booleans, null and undefined .

The typeof operator is the best one for checking for types of primitive values.

We just need to pass in the expression we want to check as the operand.

For strings, typeof returns 'string' .

For numbers, typeof returns 'number' .

For boolean, typeof returns 'boolean' .

For bigints, typeof returns 'bigint' .

And for undefined , typeof returns 'undefined' .

The basic syntax for typeof is:

typeof variable
Enter fullscreen mode Exit fullscreen mode

We can also write:

typeof(variable)
Enter fullscreen mode Exit fullscreen mode

However, the 2nd way makes tyepof looks like a function.

Therefore, we should use it without parentheses.

We can code defensively bu using the tupeof operator to check the type of the value of the expression.

For instance, we can write:

if (typeof name === "string") {
  let part = name.substring(3);
}
Enter fullscreen mode Exit fullscreen mode

to check a string.

We can write:

if (typeof count === "number") {
  setCount(count);
}
Enter fullscreen mode Exit fullscreen mode

to check for and set a number.

And:

if (typeof canShowMessage === "boolean" && canShowMessage) {
  showMessage("hello");
}
Enter fullscreen mode Exit fullscreen mode

to check for a boolean and whether it’s true or not.

And we can write:

if (typeof app === "undefined") {
  app = {
    // ....
  };
}
Enter fullscreen mode Exit fullscreen mode

to check for undefined .

Conclusion

We shouldn't make our app logic depend on the event object.

Also, checking for null isn’t good enough for checking most types of data.

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