JavaScript Best Practices for Creating Objects
Tags: codequality, webdev, programming, javascript
Published: 2021-01-27 02:14:05

**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/**

JavaScript is an easy programming language to learn. It’s easy to write programs that run and do something. However, it’s hard to account for all the use cases and write robust JavaScript code.

In this article, we’ll look at some best practices for writing robust JavaScript code.

* * *

### Use Factory Functions

Factory functions are functions that return a new instance of a constructor or class.

We can use them to create objects without writing any code with the `new` keyword to instantiate classes or constructors.

Constructors are often a confusing part of JavaScript and definitely one we can avoid if we wish to.

For instance, we can make our own factory function as follows:

In the code above, we have the `createPerson` factory function that takes a `firstName` and `lastName` parameter and returns an object with the `firstName`, `lastName`, and the `fullName` method.

We used an arrow function so that we don’t get confused with the value of `this` that’s in the returned object. Since arrow functions don’t bind to `this`, we know that the value of `this` in `fullName` is the returned object.

Factory functions can return objects with anything, so the possibilities are endless.

To use our `createPerson` factory function, we can write the following code:

```
const person = createPerson('Jane', 'Smith');
const fullName = person.fullName();
```

We created a `person` object with the `createPerson` function and then called the `fullName` method on it.

Then we get that `fullName` is ‘Jane Smith’ since `this` references the `person` object.

Many JavaScript functions like `Number` and `Boolean` are factory functions. They take any object as an argument and then return a number or boolean, respectively.

It makes our JavaScript code more robust because we don’t have to worry about class or constructor instances. We just have to think in terms of objects and composing functions.

Composing functions makes code more reusable and testable, creating more robust code because of this.

* * *

### Create Instance Methods for Constructors by Attaching to the prototype Property

When we want to create instance methods of a constructor, we should attach the methods to the `prototype` property of the constructor.

This way, when we instantiate the constructor, we can also call the methods on the instance.

A method that’s attached directly to the function is a static method that’s shared by all methods.

For instance, we can add instance methods to a constructor by attaching it to its `prototype` property as follows:

In the code above, we created a `Fruit` constructor that returns a `Fruit` instance. Then we added the `grow` instance method by writing:

```
Fruit.prototype.grow = function() {
  console.log(`${this.name} grew.`);
}
```

Then when we instantiate it as follows:

```
const fruit = new Fruit('apple');
fruit.grow();
```

Instance methods encapsulate methods inside the constructor instance, preventing it from being exposed to outside code and allowing it to make accidental changes.

Therefore, this makes our code more robust. Also, every constructor has its own responsibility since it has its own instance method. This prevents multiple constructors from doing different things to the same object.

The alternative (above) creates a copy of the `grow` instance method for each instance. The method isn’t cached, so it’s slower to use attach instance methods this way.

* * *

### Use the .type Property to Create Factory Functions That Can Create Multiple Types of Objects

Since factory functions can be composed, we can create a factory function that can create multiple types of objects.

We can differentiate between them with the `type` property, which is a conventional way to distinguish between different types of objects that we want to create.

To do this, we can write the following code:

In the code above, we have the `createPet` factory function that calls the `createDog` or `createCat` factory function depending on what kind of pet `type` we pass into `createPet`.

We also composed factory functions by calling a factory function inside the `createPet` factory function.

Now we just have to worry about one factory function (`createPet`) instead of using multiple factory functions to create different kinds of objects. This hides the complexity that’s underneath the code and thus there’s less risk of breaking things when we make changes.

* * *

### Conclusion

With factory functions, we can create them to create new objects. We can also compose them and call different ones within one factory function to do different things.

When we have a constructor function, we should attach instance methods to the `prototype` property of the constructor function so that they don’t have to be recreated all the time.