Button from Rectangle , and Rectangle can inherit from Control ... so, stop ... ").call or apply . This is an effective feature, and I use it extensively. Anyway, delegation is so convenient that sometimes it starts working against structural code discipline; moreover, the syntax may become slightly verbose. Impurities are a great compromise that allows you to borrow and have access to whole functional units using minimalistic syntax, and they work fine in the same team with prototypes. They offer the descriptive power of hierarchical inheritance without the brain problems associated with high-rise, single-root inheritance.Person , Circle , Observer ). Impurity classes are usually considered abstract in the sense that they do not have instances on their own — instead, their methods are copied (or “borrowed”) by concrete classes as “inheritance” of behavior without entering into formal relationships with the supplier of behavior.
var Circle = function() {}; Circle.prototype = { area: function() { return Math.PI * this.radius * this.radius; }, grow: function() { this.radius++; }, shrink: function() { this.radius--; } }; var circleFns = { area: function() { return Math.PI * this.radius * this.radius; }, grow: function() { this.radius++; }, shrink: function() { this.radius--; } }; extend function (sometimes called augment ). In general, extend simply copies (but does not clone) the impurity functions to the receiving object. A quick overview shows several small variations of this implementation. For example, Prototype.js skips the hasOwnProperty check (assuming the impurity does not have enumerated properties in the prototype chain), while other versions assume that you only want to copy properties from the impurity prototype. Here is a safe and flexible option ... function extend(destination, source) { for (var k in source) { if (source.hasOwnProperty(k)) { destination[k] = source[k]; } } return destination; } var RoundButton = function(radius, label) { this.radius = radius; this.label = label; }; extend(RoundButton.prototype, circleFns); extend(RoundButton.prototype, buttonFns); //etc. ... extend function. var asCircle = function() { this.area = function() { return Math.PI * this.radius * this.radius; }; this.grow = function() { this.radius++; }; this.shrink = function() { this.radius--; }; return this; }; var Circle = function(radius) { this.radius = radius; }; asCircle.call(Circle.prototype); var circle1 = new Circle(5); circle1.area(); //78.54 this always points to the recipient of the function sets, and not to an abstract object that we do not need and which we do not use; moreover, in contrast to the traditional approach, we do not need protection against unintentional copying of inherited properties, and (whatever that means) functions are now cloned, not copied. var asButton = function() { this.hover = function(bool) { bool ? mylib.appendClass('hover') : mylib.removeClass('hover'); }; this.press = function(bool) { bool ? mylib.appendClass('pressed') : mylib.removeClass('pressed'); }; this.fire = function() { return this.action(); }; return this; }; var RoundButton = function(radius, label, action) { this.radius = radius; this.label = label; this.action = action; }; asButton.call(RoundButton.prototype); asCircle.call(RoundButton.prototype); var button1 = new RoundButton(4, 'yes!', function() {return 'you said yes!'}); button1.fire(); //'you said yes!' asOval impurity with custom grow and shrink parameters: var asOval = function(options) { this.area = function() { return Math.PI * this.longRadius * this.shortRadius; }; this.ratio = function() { return this.longRadius/this.shortRadius; }; this.grow = function() { this.shortRadius += (options.growBy/this.ratio()); this.longRadius += options.growBy; }; this.shrink = function() { this.shortRadius -= (options.shrinkBy/this.ratio()); this.longRadius -= options.shrinkBy; }; return this; } var OvalButton = function(longRadius, shortRadius, label, action) { this.longRadius = longRadius; this.shortRadius = shortRadius; this.label = label; this.action = action; }; asButton.call(OvalButton.prototype); asOval.call(OvalButton.prototype, {growBy: 2, shrinkBy: 2}); var button2 = new OvalButton(3, 2, 'send', function() {return 'message sent'}); button2.area(); //18.84955592153876 button2.grow(); button2.area(); //52.35987755982988 button2.fire(); //'message sent' asRectangle with the addition of caching ... var asRectangle = (function() { function area() { return this.length * this.width; } function grow() { this.length++, this.width++; } function shrink() { this.length--, this.width--; } return function() { this.area = area; this.grow = grow; this.shrink = shrink; return this; }; })(); var RectangularButton = function(length, width, label, action) { this.length = length; this.width = width; this.label = label; this.action = action; } asButton.call(RectangularButton.prototype); asRectangle.call(RectangularButton.prototype); var button3 = new RectangularButton(4, 2, 'delete', function() {return 'deleted'}); button3.area(); //8 button3.grow(); button3.area(); //15 button3.fire(); //'deleted' asRectangle admixture with correctly asRectangle functions that allow parameterization of grow and shrink . Function.prototype.curry = function() { var fn = this; var args = [].slice.call(arguments, 0); return function() { return fn.apply(this, args.concat([].slice.call(arguments, 0))); }; } var asRectangle = (function() { function area() { return this.length * this.width; } function grow(growBy) { this.length += growBy, this.width +=growBy; } function shrink(shrinkBy) { this.length -= shrinkBy, this.width -= shrinkBy; } return function(options) { this.area = area; this.grow = grow.curry(options['growBy']); this.shrink = shrink.curry(options['shrinkBy']); return this; }; })(); asButton.call(RectangularButton.prototype); asRectangle.call(RectangularButton.prototype, {growBy: 2, shrinkBy: 2}); var button4 = new RectangularButton(2, 1, 'add', function() {return 'added'}); button4.area(); //2 button4.grow(); button4.area(); //12 button4.fire(); //'added' 
var myCircle = asCircle.call({radius:25}); myCircle.area(); //1963.50 Source: https://habr.com/ru/post/147901/
All Articles