How-to create and use mixins in JavaScript

Mixins are handy when you want to share a feature across multiple classes without using inheritance as only some of the child classes should have that feature.

We are going to implement an example of the mixin pattern with just standard JavaScript. This pattern can quite easily be applied to your classes in any of your JavaScript projects.

Lets say you have the following classes defined:

class Animal {
  constructor() {
    this._state = 'idle';
  }

  get state() {
    return this._state;
  }
}

class Bird extends Animal {
  walk() {
    this._state = 'walking';
  }
}

class Blackbird extends Bird {}
class Swan extends Bird {}
class Ostrich extends Bird {}

Now imagine that we want the Blackbird and Swan to be able to fly as well as walk. We cannot add a fly method to the Bird class as an Ostrich cannot fly. This is where a mixin can come in handy.

Let's create a mixin and apply it to one of our fliers.

function Flyer(superclass) {
  return class extends superclass {
    fly() {
      this._state = 'flying';
    }
  };
}

class Swan extends Flyer(Bird) {}

Neat! Let's break it down part by part.

First, we create a new function called Flyer that takes a class as an argument:

function Flyer(superclass) {

Then we let that function create and return a new anonymous class (yes anonymous classes are allowed) which extends the superclass passed in to the Flyer function:

function Flyer(superclass) {
  return class extends superclass {

Finally we add the fly method to the anonymous class that we just created:

function Flyer(superclass) {
  return class extends superclass {
    fly() {
      this._state = 'flying';
    }
  }
}

That is all that is needed. Mixins can also be chained, let's make the swan a Swimmer as well.

function Swimmer(superclass) {
  return class extends superclass {
    swim() {
      this._state = 'swimming';
    }
  }
}

class Swan extends Swimmer(Flyer(Bird)) {}

Lets put it all together:

class Animal {
  constructor() {
    this._state = 'idle';
  }

  get state() {
    return this._state;
  }
}

class Bird extends Animal {
  walk() {
    this._state = 'walking';
  }
}

function Flyer(superclass) {
  return class extends superclass {
    fly() {
      this._state = 'flying';
    }
  }
}

function Swimmer(superclass) {
  return class extends superclass {
    swim() {
      this._state = 'swimming';
    }
  }
}

class Blackbird extends Flyer(Bird) {}
class Swan extends Swimmer(Flyer(Bird)) {}
class Ostrich extends Bird {}

const blackbird = new Blackbird();
blackbird.fly();

const swan = new Swan();
swan.fly();
swan.swim();

const ostrich = new Ostrich();
ostrich.fly(); // Throws an error as the Ostrich have no fly method

This can be a really powerful pattern to structure projects, but do keep in mind that it also might introduce some new challenges as you cannot for example do swan instanceof Swimmer (as you could with Animal or Bird) as the mixin class is an anonymous class. Also if overused and classes are to broken up into a large number of small mixins it can become hard to know exactly which methods that are available on which class without debugging the instantiated class.

Still, the pattern can be really useful if used with caution.