JavaScript Refactoring — Functions and Classes

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 classes.

Remove Assignments to Parameters

We should remove the assignment of values to parameters and assign parameter values to variables before working with them.

For instance, instead of writing the following:

const discount = (subtotal) => {
  if (subtotal > 50) {
    subtotal *= 0.8;
  }
}
Enter fullscreen mode Exit fullscreen mode

We write:

const discount = (subtotal) => {
  let _subtotal = subtotal;
  if (_subtotal > 50) {
    _subtotal *= 0.8;
  }
}
Enter fullscreen mode Exit fullscreen mode

We should do that because people may be confused if the parameter is passed by value or passed by reference.

In this case, it’s passed by value, but to make that clear, we should assign it to a variable before working with it.

Replace Method with a Function

We can turn a method into its own function so that all classes can access it.

For instance, instead of writing the following:

const hello = () => {
  console.log('hello');
}

class Foo {
  hello() {
    console.log('hello');
  }
  //...
}
class Bar {
  hello() {
    console.log('hello');
  }
  //...
}
Enter fullscreen mode Exit fullscreen mode

We can extract the hello method into its own function as follows:

const hello = () => {
  console.log('hello');
}

class Foo {
  //...
}

class Bar {
  //...
}
Enter fullscreen mode Exit fullscreen mode

Since the hello method doesn’t depend on this and are duplicated in both classes, we should move it out to its own function to avoid duplication.

Substitute Algorithm

We want to replace an algorithm with one that’s clearer.

For instance, instead of writing the following:

We instead write the following:

const doubleAll = (arr) => {
  return arr.map(a => a * 2);
}
Enter fullscreen mode Exit fullscreen mode

We made our doubleAll function more concise by replacing the loop with array methods that does the same thing.

They both double each entry of the array and return it.

If there’s a simpler way to do something, then we should use that instead.

Move Method

We can move a method between classes to another so that it’s in the place that it’s actually used.

For instance, instead of writing the following code:

class Foo {
  method() {}
}

class Bar {

}
Enter fullscreen mode Exit fullscreen mode

We can instead write the following:

class Foo {

}

class Bar {
  method() {}
}
Enter fullscreen mode Exit fullscreen mode

We move methods so that it’s in the class that uses the method the most. The original class can call the method from the new class that the method is in.

Or it can just not be called if it isn’t needed.

Move Field

In addition to moving methods, we can move fields as well.

For instance, instead of writing the following:

class Foo {
  constructor(foo) {
    this.foo = foo;
  }
}

class Bar {

}
Enter fullscreen mode Exit fullscreen mode

We can instead write the following:

class Foo {

}

class Bar {
  constructor(foo) {
    this.foo = foo;
  }
}
Enter fullscreen mode Exit fullscreen mode

We can move it to the place that we need it the most.

Extract Class

If our class is complex and does multiple things, then we can move the extra function to the new class.

For instance, instead of writing the following:

class Person {
  constructor(name, phoneNumber) {
    this.name = name;
    this.phoneNumber = phoneNumber;
  }

  addAreaCode(areaCode) {
    return `${areaCode}-${this.phoneNumber}`
  }
}
Enter fullscreen mode Exit fullscreen mode

We can write the following instead:

class PhoneNumber {
  constructor(phoneNumber) {
    this.phoneNumber = phoneNumber;
  }

  addAreaCode(areaCode) {
    return `${areaCode}-${this.phoneNumber}`
  }
}

class Person {
  constructor(name, phoneNumber) {
    this.name = name;
    this.phoneNumber = new PhoneNumber(phoneNumber);
  }
}
Enter fullscreen mode Exit fullscreen mode

This way, we move the extra functionality that the Person class shouldn’t, i.e. manipulating phone numbers into its own class.

By doing that, both classes only do one thing instead of having one class do multiple things.

Conclusion

We can extract code from complex classes that does multiple things into its own class.

Also, we can move methods and fields around the place where it’s used the most.

Assigning values to parameter values is confusing, so we should assign it to a variable before working with them.

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