How to add mixins to ES6 javascript classes?

Javascript's object/property system is much more dynamic than most languages, so it's very easy to add functionality to an object. As functions are first-class objects, they can be added to an object in exactly the same way. Object.assign is the way to add the properties of one object to another object. (Its behaviour is in many ways comparable to _.mixin.)

Classes in Javascript are only syntactic sugar that makes adding a constructor/prototype pair easy and clear. The functionality hasn't changed from pre-ES6 code.

You can add the property to the prototype:

Object.assign(Test.prototype, mixin);

You could add it in the constructor to every object created:

constructor() {
    this.var1 = 'var1';
    Object.assign(this, mixin);
}

You could add it in the constructor based on a condition:

constructor() {
    this.var1 = 'var1';
    if (someCondition) {
        Object.assign(this, mixin);
    }
}

Or you could assign it to an object after it is created:

let test = new Test();
Object.assign(test, mixin);

I'm surprised to find that none of the answers mentions what I would consider a mixin in the sense of composition (and in contrast to inheritance), which to me is a function that adds functionality to an object. Here's an example making use of both inheritance and composition:

class Pet { constructor(name) { this.name = name } }
class Cat extends Pet { expression = 'miaow' }
class Dog extends Pet { expression = 'bark' }

class Human { constructor(name, age) { this.name = name; this.age = age; } }
class American extends Human { expression = 'say howdy' }

function canSayHello(...contexts) {
  for (const context of contexts) {
    context.sayHello = function() {
     console.log(`Hello my name is ${this.name} and I ${this.expression}`)
    }
  }
}

canSayHello(Pet.prototype, Human.prototype); // apply the mixin

const garfield = new Cat('garfield');
const pluto = new Dog('pluto');
const joebiden = new American('Joe Biden', 79); 

garfield.sayHello();
pluto.sayHello();
joebiden.sayHello();

You should probably look at Object.assign(). Gotta look something like this:

Object.assign(Test.prototype, mixin);

This will make sure all methods and properties from mixin will be copied into Test constructor's prototype object.


In es6 you can do this without assigning and you can even invoke the mixin constructor at the correct time!

http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/#bettermixinsthroughclassexpressions

This pattern uses class expressions to create a new base class for every mixin.

let MyMixin = (superclass) => class extends superclass {
  foo() {
    console.log('foo from MyMixin');
  }
};
class MyClass extends MyMixin(MyBaseClass) {
  /* ... */
}