Mixin

ref – https://javascript.info/mixins

a mixin provides methods that implement a certain behavior, but we do not use it alone, we use it to

add to the behavior to other classes

.

In other words, mixins are used to extend the behavior of objects by providing a set of reusable functions.

It is used to modularize functionality. For example, if you have a class with all sorts of functionalities, it will become messy and unmanageable. But if you use mixins, you can modularize the functionality and thus, making it much easier to maintain.

The simplest way to make a mixin in JavaScript is to make an object with useful methods. This acts as a prototype object. We then can create other literal objects and extend from this object. This adds additional functionalities to it. In essence, we are “mixing in” additional methods. Finally, we take this hierarchy of a prototype object, and can easily merge them into a prototype of any class.

Creating a mixin

First, we’ll create a literal object “sayMixin”. It will act as a base prototype.

Note that all objects derive from “Object”. When we create our literal object, its __proto__ will automatically be referencing Object Prototype. In the diagram, you’ll notice “extend” in Object Prototype. That’s simply a function defined in a previous example:

So whatever functionality you add to Object prototype will be inherited by all objects you create.

On to the example…

Thne, we want to extend from sayMixin. So we create another literal object. A literal object has a __proto__ property. In order to extend this object from another, we point the __proto__ to the base object “sayMixin”.

Then, we define our functionality, and in order to call the base object, we use super. Then we simply access the functions/properties of super.

The digram of the hierarchy looks like this:

Using the Mixin

Now that we have our mixin prototype object created, we want to use start using it!

So first, we create a constructor function User.

Then we add functionality to its prototype like so:

“new” will be used to instantiate it.

So diagram wise, it looks like this:

in order to add our mixin prototype features into it, we use Object.assign to carry all owned properties and functions over to User. This is so that you don’t over-ride anything in User’s prototype object, such as logInfo.

By definition

The Object.assign() method only copies enumerable and own properties from a source object to a target object.

Thus, we created a base prototype object in sayMixin, extended it to sayHiMixin, and finally, copied all its traits to User’s prototype object.

Hence, bringing over a new prototype object into User’s current available prototype object, and “mixin” them via Object.assign is what this is all about.

Thus, now we have successfully “mixed in” another prototype into User’s prototype.


output:

User { name: ‘Dude’ }

User {
logInfo: [Function],
sayHi: [Function: sayHi],
sayBye: [Function: sayBye]
}

Dude, is a cool person!
Hello Dude
Bye Dude

Mixins can make use of inheritance inside themselves

First, we set up the skeleton code.

We create a literal object with function properties. Each function takes a string for the event name, and a function handler so that we have a reference to the function.

Then we make a class called Menu. This class has a function called choose. When executed, calling “choose” will make whatever object it owns to call trigger.

Now, the idea is that an object should have a method to “generate an event” when something important happens to it, and other objects should be able to “listen” to such events.

full source

Now, you see, when the menu gets selected, we can notify other objects via callbacks.

JavaScript does not support multiple inheritance, but mixins can be implemented by copying them into the prototype.

We can use mixins as a way to augment a class by multiple behaviors, like event-handling as we have seen above.

Mixins may become a point of conflict if they occasionally overwrite native class methods. So generally one should think well about the naming for a mixin, to minimize such possibility.

BluePrints for mixins

Sometimes however mixins require private state. For example the eventEmitter mixin would be more secure if it stored its event listeners in a private variable instead of on the “this” object.

To recap, we created a menu like so:

we created an object menu, with its prototype having properties from eventMixin.

When we register an object for an event say “select”:

the on function has lazy loaded the property _eventHandlers, which is object of “string : array” index value pairs.

at this point if you were to analyze the _eventHandlers property:


output:

{ select:
[ [Function: sendOff],
[Function: openPage],
[Function: sendEmail] ] }

It would show that the “select” value would match up to three handlers.

This public access of this property is bad, and this is what we’re trying to solve. However mixins have no create function to encapsulate private state. Hence we create “blueprints” of mixins to create closures. Blueprints may look like constructor functions but they are not meant to be used as constructors.

A blueprint is used to extend an object via concatenation after it’s created.
In the create function, you then use the allocated object in rectangle.extend (self), and use .call on it for eventEmitter.
At that step, you then append all functionalities in eventEmitter onto the allocated object from rectangle.create.call.

That way, private variable events stay in eventEmitter. And eventEmitter’s functions stay public for the allocated object form rectangle.extend.

Blueprints are unique to JavaScript. They are a powerful feature. However they have their own disadvantages. The following table compares the advantages and disadvantages of mixins and blueprints:

mixins
They are used to extend prototypes of objects. Hence objects share the same blueprint functions.
No private state due to lack of an encapsulating function.
They are static prototypes and can’t be customized.

blueprints
They are used to extend newly created objects. Hence every object has its own set of blueprint functions.
They are functions, and hence they encapsulate private state.
They can be passed arguments to customize the object.