JavaScript Design Patterns — Composition, Inheritance, and Configuration
Tags: webdev, programming, javascript, architecture
Published: 2021-01-30 21:28:37

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


Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the difference between composition and inheritance, and look at why we should make our program have some flexibility.

### Composition Versus Inheritance

Composition is when our object contains other objects.

Inheritance is when we receive the parent object’s members in the current object.

They both have their place.

Composition is a has-a relationship while inheritance is a has-a relationship.

It’s very important to make distinctions between the 2 since they do different things.

In JavaScript, there’re various ways that 2 things are composed.

For instance, we can have functions that are nested in other functions.

We can write:

```
const foo = fn => {
  //...
  fn();
  //...
}
```

We have a `foo` function that calls `fn` .

Also, we can have nested objects. For example, we can write:

```
const obj = {
  foo: 1,
  bar: {
    baz: 2,
  }
}
```

We have an object as the value of `bar` .

We can also have functions as values of object properties.

Composition is used for holding functionality that’s needed by something.

Inheritance, on the other hand, is an is-a relationship.

This means a child object is also a parent object. It’s just that a child object may have additional things.

For instance, if we have:

```
class Animal {
  //...
}

class Cat extends Animal {
  //...
}
```

Then `Cat` is a subclass of `Animal` . `Cat` is an animal.

`Cat` shares all the members of `Animal` .

We can any methods of`Animal` and access any instance variables of `Animal` from a `Cat` instance.

For example, we can write:

```
class Animal {
  speak() {
    //...
  }
}
class Cat extends Animal {
  //...
}
```

The `extends` keyword indicates that `Cat` inherits the members of `Animal` .

Then if we create a `Cat` instance, we can write:

```
const cat = new Cat();
```

Then we can call `speak` by calling:

```
cat.speak();
```

Likewise, we can create an is-a relationship between 2 objects with the `Object.create` method:

```
const animal = {
  speak() {
    //...
  }
}

const cat = Object.create(animal);
```

`Object.create` takes a prototype object which will be the prototype of the child object.

So `animal` is the parent of `cat` in the example above.

Like with class instances, we can call `speak` by writing `cat.speak()` .

In both the class and object examples, the prototype of the object resides in the `__proto__` property of the object.

Inheritance is good for creating multiple classes or objects that share things from the parent class or object respectively.

The general principle is that if we have volatile code, then we should use more has-a relationships rather than an is-a relationship since we assume that shared code between a parent and different children may change.

If we change shared code between parents and children, then we break all the children as well.

### Creating Algorithms

Once we decided on the patterns to use, then we’ve to devise our algorithm for our program.

This should be easy once we created some basic designs. Implementation is all that’s needed in most cases.

We can use existing libraries to make our lives easier, which is what we should do in most cases.

If we have an is-a relationship between classes or objects, then we need to think about which pieces of code are shared and which ones are unique to classes or objects.

If we use a has-a model instead, then we can create algorithms in different places and use them as we wish to.

We should think about making our program configurable so that we don’t have to change code to have slightly different functionality.

This way, we make our lives easier since code change always has some risks.

To reduce that, we should make things that change frequently be configurable so that we don’t have to deal with them.

For instance, we can read settings from a file or database so an algorithm can be selected according to settings that are set in those places.

### Conclusion

Our programs should have some flexibility so that we don’t have to change code for it to do different things.

Composition is when we have something in an object or class so we can use them as we wish.

Inheritance is when we have some shared code that’s used by other objects or classes.