Mixins in JavaScript


Multiple-inheritance is not supported by Javascript by default. But sometimes we need to mix multiple object properties into a single object. Object property sharing can be done using mixins. In this article, we shall cover what are mixins in JavaScript.

The definition of mixins can be stated as mixins is a class that contains methods that can be used by other classes without inheriting from that class. The methods in mixin provide certain behavior which is not used alone but can be used to add these behaviors to other classes.

Mixin: A Simple Example

See the following example where we have a smart home appliance named DoodleHome and another speaker object named DoodleSpeak. Some messages are already defined in the DoodleSpeak object which is being used in DoodleHome.

Example

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { let DoodleSpeak = { doodleHello() { content += 'Hello! ' + this.name + "<br>"; }, doodleBye() { content += 'Good Bye! ' + this.name + "<br>"; }, }; class DoodleHome { constructor(name) { this.name = name; } } // copy the methods from Object.assign(DoodleHome.prototype, DoodleSpeak); doodly = new DoodleHome("Doodly"); mixi = new DoodleHome("Mixi") doodly.doodleHello(); mixi.doodleHello(); doodly.doodleBye(); mixi.doodleBye(); } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

In this example, the DoodleHome object is assigned to another class DoodleSpeak. This assigns () method plays an important role in the mixin. A mixin can make use of inheritance inside themselves. For instance, if we create an object type DoodleSay() and that is implemented inside DoodleSpeak in a more generalized form it will be a better implementation. Let us see the following example to understand this concept.

Example

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { let DoodleSay = { saySomething(statement) { content += statement + "<br>"; } }; let DoodleSpeak = { __proto__: DoodleSay, doodleHello() { super.saySomething(`Hello! ${this.name}`); }, doodleBye() { super.saySomething(`Good Bye! ${this.name}`); }, }; class DoodleHome { constructor(name) { this.name = name; } } // copy the methods from DoodleSpeak Object.assign(DoodleHome.prototype, DoodleSpeak); doodly = new DoodleHome("Doodly"); mixi = new DoodleHome("Mixi") doodly.doodleHello(); mixi.doodleHello(); doodly.doodleBye(); mixi.doodleBye(); } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

Example

Let us see another example with super classes and class mixins

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { let DoodleSay = { saySomething(statement) { content += statement + "<br>"; } }; class Animal { constructor() { this._state = 'not moving, stays idle'; } get state() { return this._state; } } class Bird extends Animal { walk() { this._state = 'walking on ground'; } } function Flyer(parentClass) { return class extends parentClass { fly() { this._state = 'flying in the sky'; } } } function Swimmer(parentClass) { return class extends parentClass { swim() { this._state = 'swimming in water'; } } } class Crow extends Flyer(Bird) { } class Duck extends Swimmer(Flyer(Bird)) { } class Penguin extends Bird { } const crowObj = new Crow(); crowObj.fly(); content += 'State of the CROW: ' + JSON.stringify(crowObj.state) + "<br>"; const duckObj = new Duck(); duckObj.fly(); duckObj.swim(); content += 'State of the DUCK: ' + JSON.stringify(duckObj.state) + "<br>"; const penguinObj = new Penguin(); penguinObj.fly(); // Throws an error as the Penguin have no fly method } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

In this example, we have defined a few classes like Animal, and Bird which are a subclass of Animal. All animals are idle at present and the bird class type has walk property so that all birds can walk. The Flyer function will create a class taking one parent class type which will assign fly() property and similarly Swimmer class will return another class type with swim property. These different class types are merged for some objects. In this example, Crow, Duck, and Penguin all are birds but the swim property is assigned to Duck, Crow and Duck can fly also but Penguin has no fly() property, so it is returning an error stating− “TypeError: penguinObj.fly is not a function”

Advantages and Limitations of Mixins

In JavaScript, Mixins decrease the functional repetition and multiple function reuse in a system. Sometimes we need shared behavior across object instances, we can easily avoid any duplication by maintaining this shared functionality in a Mixin so by focusing on implementing only the functionality in our system which is truly needed and unique.

Limitations in Mixins are a little bit confusing. Some developers feel that injectingfunctionality into an object prototype is not a good idea as it inserts unnecessary code inside objects and a level of uncertainty regarding the origin of our functions.

Conclusion

Javascript is not a completely object-oriented language. For that reason, multiple inheritance is not directly supported by JavaScript. We can use the concept of Mixin to get the effect of property copying from different objects to one single object. We can define multiple classes or object types with their property, then merge them using apply() method from one class to another set of classes.

Updated on: 23-Aug-2022

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements