AlgorithmsCodilityPatternsTutorials

Mixins

are a hot topic in almost all popular languages. The main reason is that they make inheritance much easier, once you wrap your head around it. The official definition of mixin, as proposed by Gilad Bracha and William Cook in their book Mixin-based Inheritance goes like this:

A mixin is an abstract subclass; i.e. a subclass definition that may be applied to different superclasses to create a related family of modified classes.

So basically, mixin is supposed to sit between a superclass and a subclass, or at the end of the chain, extending the objects functionality. Javascript has no default mixin implementation, but as a flexible language, there are numerous variants and opinions of how mixins should look like or what they are. Dart, as a language that compiles to javascript has a very neat implementation of mixins.

Neat!
For all us non Dart JS developers, we are stuck using an implementation somewhat similar to a decorators. A pure function that modifies an object after it has been created or creates a new one by copying props from given objects. Before Object.assign, that simply copies the properties that it has been provided, we had to use jQuery.extend or _.extend utility functions. All those methods basically do the same thing, and that is the JS implementation of the mixin pattern. (Not entirely true, read on…)

Although it seems as a great idea, simply copying properties has it’s pitfalls. For example, you cant use isPrototypeOf or isInstanceOf, or when you are merging a prototype with some object, all the objects that inherit from that prototype are also seeing that change.

To implement the pattern as it is originally defined, and add a mixin later,  i guess you could simulate a function that will take the subclass prototype property, store it, add a mixin in it’s place and set the mixins prototype with the original superclass. But due to the complexity and expense of the operation, that is almost never the case.

ES6 brought us classes, and using them, this idea is doable!

Maybe the closest implementation of the pattern regarding it’s original definition is to apply the mixin to a superclass that we are extending.

First define the mixin function that takes a superclass as it’s argument, and returns a class that extends,

And MyClass now has a foo method via mixin inheritance:

Traits.

Basically, traits are mixins that don’t let you simply override the preceding object’s property. You must explicitly state what happens in case of properties with the same name. In Javascript, the most popular library is Traits.js. It has a few nicely documented methods, and mastering them can prove very beneficial! I wont go into details here, if you are interested take a look at this.

And lastly,

Stamps.

Stamp is a relatively new player on the Javascript scene, as it comes from frustration of watching classical inheritance languages programmers trying to set up complex tree hierarchies in Javascript by misusing the language 🙂

They come in three main types, one for defining prototype methods via delegation, one for mixins/cloning, and one for ensuring privacy via closure.

I can not explain this any better than the author has, so either read the part of the docs i copied here, or take a look at the whole documentation

A stamp is a composable factory function. Stamps allow you to inherit easily from multiple ancestors by composing multiple source stamps. You can combine properties, methods, and initializers (with closures) from any number of stamps to produce a new stamp. Stamps are more flexible than traditional factory functions or classical multiple inheritance. Traditional factory functions can’t be composed together to produce new factory functions. Class inheritance does not provide a standardized mechanism for class composition.

Stamp composition takes advantage of three different kinds of prototypal inheritance:

  • Differential inheritance, aka delegation (e.g., JavaScript’s [[Prototype]]),
  • Mixins/cloning with optional deep merge, aka concatenative inheritance (e.g., JavaScript’s Object.assign()),
  • Functional / closure inheritance (for initialization or privacy/encapsulation)

When invoked the stamp factory function creates and returns object instances assigning: