⬆️ ⬇️

Javascript impurity for dummies

After it became seemingly clear with the classical (from the word class) inheritance in JS, I decided to deal with the implementation of another way to reuse the code - impurities. Despite the rather unusual name, this way is pretty darn simple.





1. Impurities - this is, in fact, what?



Mixin is an object with a set of functions that is not used by itself (separately from other objects).



For example, a wonderful admixture:

')

var Mixin_Babbler = { say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'"); }, argue: function() { console.log("You're totally wrong"); } }; 


When you try to call the say method just like that, a bummer awaits us, because neither this.name nor this.THOUGHTS in our object, for some reason, simply does not.

In fact, everything is correct; in order to use the impurity as intended, we need another object, and a method that copies all the properties of the impurity objects transferred to it into the prototype of the constructor function — usually this method is called extend, or mix, or something like this:



 function extend(object) { var mixins = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < mixins.length; ++i) { for (var prop in mixins[i]) { if (typeof object.prototype[prop] === "undefined") { object.prototype[prop] = mixins[i][prop]; } } } } 


2. So how to use it?



Easily and without straining - let's say we have a couple of impurities:



 var Mixin_Babbler = { say: function () { console.log("My name is " + this.name + " and i think:'" + this.THOUGHTS + "'"); }, argue: function() { console.log("You're totally wrong"); } }; var Mixin_BeverageLover = { drink: function () { console.log("* drinking " + this.FAVORITE_BEVERAGE + " *"); } }; 


And, to someone, perhaps, already familiar, evolutionary chain:



 function Man(name) { this.name = name; } Man.prototype = { constructor: Man, THOUGHTS: "I like soccer" } extend(Man, Mixin_Babbler); function Gentleman(name) { this.name = name; } Gentleman.prototype = { constructor: Gentleman, THOUGHTS: "I like Earl Grey", FAVORITE_BEVERAGE: "Tea" } extend(Gentleman, Mixin_Babbler, Mixin_BeverageLover); function Programmer(name) { this.name = name; } Programmer.prototype = { constructor: Programmer, THOUGHTS: "MVC, MVVM, MVP *___* like it!", FAVORITE_BEVERAGE: "Cofee", write_good_code: function () { console.log("*writing best code ever*"); this.drink(); } } extend(Programmer, Mixin_Babbler, Mixin_BeverageLover); 


Each "class" is now independent of the other, and the entire repeating functional is implemented with the help of impurities.



Now it's worth checking everything - it will suddenly work:



 var man = new Man("Bob"); var gentleman = new Gentleman("Bill"); var programmer = new Programmer("Benjamin"); man.say(); man.argue(); gentleman.say(); gentleman.drink(); programmer.say(); programmer.write_good_code(); 


And the console says that yes, everything is as it should:



 My name is Bob and i think:'I like soccer' *You're totally wrong* My name is Bill and i think:'I like Earl Grey' *drinking Tea* My name is Benjamin and i think:'MVC, MVVM, MVP like *__* it!' *writing best code ever* *drinking Cofee* 


Actually everything. In contrast to the "classical" inheritance, the implementation of impurities is very simple and clear. There are of course some variations, but somehow the kernel looks like this.



UPD. As suggested by one very good person with the nickname lalaki , the extend method can be implemented a little differently:



 function extend_2(object) { var mixins = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < mixins.length; ++i) { for (var prop in mixins[i]) { if (typeof object.prototype[prop] === "undefined") { bindMethod = function (mixin, prop) { return function () { mixin[prop].apply(this, arguments) } } object.prototype[prop] = bindMethod(mixins[i], prop); } } } } 




With this approach, it is possible to replace methods on the fly with impurities, and these changes will immediately be available to all objects using this mixture.

A very, very small flaw is that a not too smart hint in the development environment will always show that the methods have no arguments.



All code and examples lie quietly here.

Source: https://habr.com/ru/post/132340/



All Articles