Subclass Factory Mixins
There is another way to realize mixins in Javascript: With subclass factories.
A subclass factory is a function that excepts a base class and returns an extended subclass of this base class:
const mixin = base => class extends base {
/* properties to mix in */
}
Subclass factories are possible for two reasons:
class
es can be defined as expressions and are first class* in Javascriptextends
clauses can contain arbitrary expressions
Let’s apply this pattern:
// superclass
class CartoonCharacter {
constructor(author) { this.author = author }
drawnBy() { return "drawn by " + this.author }
}
// mixin 1
const Human = base => class extends base {
haveFun() { return "drinking beer" }
}
// mixin 2
const Simpson = base => class extends base {}
// composed subclass
const Homer = Simpson(Human(CartoonCharacter));
// create an instance
const homer = new Homer("Matt Groening")
console.log(homer.drawnBy());
console.log(homer.haveFun());
What are the advantages of mixins by sublcass factories?
- natural property precedence: Later mixed in properties override prior properties of the same name
- both mixins (
Human
/Simpson
) and subclasses (Homer
) can usesuper
as usual - mixins can have constructors (stateful mixins)
- no mutation of prototypes or instances
Stateful Mixins
State makes things hard. You should avoid state, whenever possible. However, sometimes your mixin needs its own state, which is passed through a constructor:
class CartoonCharacter {
constructor(author) { this.author = author }
drawnBy() { return "drawn by " + this.author }
}
const Human = base => class extends base {
haveFun() { return "drinking beer" }
}
const Simpson = base => class extends base {
constructor(arg, ...superArgs) {
super(...superArgs);
this.name = arg;
}
sayHey() { return "Hey, I am " + this.name }
}
const Homer = Simpson(Human(CartoonCharacter));
const homer = new Homer("Homer Simpson", "Matt Groening")
console.log(homer.drawnBy());
console.log(homer.haveFun());
console.log(homer.sayHey());
*the term first class functions means that functions can be passed around as arguments or return values like normal data