JavaScript Refactoring — Function Refactorings

John Au-Yeung - Jan 25 '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/

We can clean up our JavaScript code so that we can work with them more easily.

In this article, we’ll look at some refactoring ideas that are relevant for cleaning up JavaScript functions and methods.

Extract Method

We turn some code fragment into a function that has its own name to explain what they’re doing.

Instead of writing the following code:

const logOwing = (name, amount) => {
  console.log('name', name);
  console.log('amount', amount);
}
Enter fullscreen mode Exit fullscreen mode

We can instead move the log statements into their own function as follows:

const logName = (name) => {
  console.log('name', name);
}

const logAmount = (amount) => {
  console.log('amount', amount);
}

const logOwing = (name, amount) => {
  logName(name);
  logName(amount);
}
Enter fullscreen mode Exit fullscreen mode

This way, we know what each statement is doing.

Inline Method

We can put the function’s body into the body of its callers and remove the function.

Instead of having a function that only returns the return value of one expression as follows:

const getRating = (isLate) => {
  return (isLate) ? 1 : 21;
}
const getDeliverPersonRating = () => {
  getRating(false)
}
Enter fullscreen mode Exit fullscreen mode

We just move the expression of the getRating function into the getDeliverPersonRating function as follows:

const getDeliverPersonRating = () => {
  const isLate = false;
  return (isLate) ? 1 : 21;
}
Enter fullscreen mode Exit fullscreen mode

The method is getDeliverPersonRating is clear from its name, so we don’t need another function doing the same thing, so we just move the expression in the getRating function into the getDeliverPersonRating function.

Inline Temp

We can remove variables that are assigned the return value of some function and combine it with the expression that uses the temporary variable.

For instance, instead of writing the following:

const getBasePrice = () => {
  return 2
}

const isHighPrice = () => {
  const basePrice = getBasePrice();
  return basePrice > 2;
}
Enter fullscreen mode Exit fullscreen mode

We can remove the basePrice constant and just replace it with the getBasePrice call as follows:

const getBasePrice = () => {
  return 2
}

const isHighPrice = () => {
  return getBasePrice() > 2;
}
Enter fullscreen mode Exit fullscreen mode

We can do that since the basePrice constant is just used in one place, so we don’t really need to assign it to a variable or constant and then reference it.

They just encourage longer methods.

Introduce Explaining Variable

If we have a complex expression, we should assign it to a variable so that we can see what the expression returns without looking at the expression itself.

For instance, instead of writing the following code:

const checkBrowser = () => {
  if (navigator.userAgent.toLowerCase().includes("mac") &&
    navigator.userAgent.toLowerCase().includes("ie")) {
    //...
  }
}
Enter fullscreen mode Exit fullscreen mode

We can introduce some variables to check the user agent as follows:

const checkBrowser = () => {
  let userAgent = navigator.userAgent.toLowerCase()
  let ieIEMac = userAgent.includes("mac") && userAgent.toLowerCase().includes("ie")
  if (ieIEMac) {
    //...
  }
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we set the user agent string to the userAgent variable and then the ieIEMac is set to the boolean expression to check if the browser’s user agent string he 'ie' and 'mac' in it.

Now we know without looking at the long boolean expression that it’s checking if the user is visiting a site with IE on a Mac.

It makes reading our code easier.

Split Temporary Variable

We should make a temporary variable for each assignment if we’re assigning 2 different values to the same variable.

Instead of writing the following:

const getCircleDimensions = (radius) => {
  let temp = 2 * Math.PI.radius;
  const result = {};
  result.perimeter = temp;
  temp = Math.PI * (radius ** 2);
  result.area = temp;
  return result;
}
Enter fullscreen mode Exit fullscreen mode

We write the following:

const getCircleDimensions = (radius) => {
  const perimeter = 2 * Math.PI.radius;
  const area = Math.PI * (radius ** 2);
  return {
    perimeter,
    area
  };
}
Enter fullscreen mode Exit fullscreen mode

In the code above, we have the getCircleDimensions function, which calculates the perimeter and area of a circle with the given radius.

In the first function, we assigned the return value for the perimeter and area to the same temp variable, and then assigned each to as values of different properties of result .

In the refactored version, we set them each to their own constant and then return them in the object.

It’s both shorter and clearer. We want to refactor the function this way so that we can just look at the constant names to get what we’re doing.

Conclusion

There’re few ways to refactor JavaScript code. We can introduce temporary variable to make things clearer or we can remove them if the code is clear without it.

We can do the same with help functions.

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