JavaScript Mixins

In JavaScript, it is possible to inherit only from one object. There can be a single [[Prototype]] for an object. A class can extend only one class.

But, at times it can meet limiting. For example, you have a StreetSweeper class and a class Bike and intend to mix them and have StreetSweepingBicycle. In this case, you can use the concept, called “mixins”.

A mixin can be described as a class, which contains methods that can be used by other classes without inheriting from it. That is, mixin provides methods implementing a specific behavior. It is not used alone but for adding the behavior to other classes.

Discovering Mixins on Examples

In JavaScript, the easiest way of implementing a mixin is to create an object with efficient methods, so that one could merge them to a prototype of any class.

In the example below, sayWelcomeMixin is applied for adding “speech” to the user:

// mixin
let sayWelcomeMixin = {
  sayWelcome() {
    console.log(`Welcome ${this.userName}`);
  },
  sayBye() {
    console.log(`Bye ${this.userName}`);
  }
};
class User {
  constructor(userName) {
    this.userName = userName;
  }
}
// copy the methods
Object.assign(User.prototype, sayWelcomeMixin);
// now User can say welcome
new User("John").sayWelcome(); // Welcome John!

So, there is no inheritance just copying. Hence, User can inherit from another class, including the mixin to mix in additional methods, as follows:

class User extends Person {
  // ...
}
Object.assign(User.prototype, sayWelcomeMixin);

Also, mixins can benefit from inheritance between themselves.

Let’s see the following case:

let sayMixin = {
  say(phrase) {
    console.log(phrase);
  }
};
let sayWelcomeMixin = {
  __proto__: sayMixin, //(or Object.create can be used to set the prototype here)
  sayWelcome() {
    // calling the parent method
    super.say(`Welcome ${this.name}`);
  },
  sayBye() {
    super.say(`Bye ${this.name}`); 
  }
};
class User {
  constructor(name) {
    this.name = name;
  }
}
// copy the methods
Object.assign(User.prototype, sayWelcomeMixin);
// now User can say hi
new User("John").sayWelcome(); // Welcome John!

Consider that calling to the parent method super.say() from sayWelcomeMixin.

EventMixin

An essential feature of many browser objects is the ability to generate events. Let’s try to create a mixin that will allow to easily add event-related functions to any object/class.

Mixin provides the .trigger(name, [...data]) method for generating an event when an important thing happens to it. The name of the event is denoted by the name argument. It is followed by additional arguments.

Also, the method .on(name, handler), adding the handler function as the listener to events with the given name. It is called when an event with a given name is occurs, getting the arguments from the .trigger call. and, finally, the .off(name, handler) method deletes the handler listener.

After adding the mixin, an event "login" is generated by the object user whenever the visitor logs in.

A menu is capable of generating the "select" event when an item of menu is selected. Other objects can assign handlers for reacting to that event.

Summary

Mixin is considered a generic object-oriented programming term. It is a class containing methods for other classes.

Multiple inheritances aren’t supported by JavaScript, but mixins may be performed via copying methods into prototype. Mixins can also be used for augmenting a class by adding multiple behaviors such as event-handling.

Sometimes mixins can become a point of conflict (for instance, when they accidentally overwrite the existing method of the class). Therefore, it would be best if you thought well about naming methods of a mixin to minimize the risks.




Do you find this helpful?

Related articles