Button от Rectangle, а Rectangle может наследоваться от Control… так, стоп…»).call или apply. Это эффективная особенность, и я широко ее использую. Как бы то ни было, делегирование столь удобно, что иногда начинает работать против структурной дисциплины кода; более того, синтаксис может стать слегка многословным. Примеси — отличный компромисс, который позволяет заимствовать и иметь доступ к целым функциональным единицам с помощью минималистичного синтаксиса, и они отлично работают в одной упряжке с прототипами. Они предлагают описательную мощь иерархического наследования без мозголомных проблем, связанных с многоэтажным, восходящим к одному корню наследованием.Person, Circle, Observer). Примесные классы обычно считаются абстрактными в том смысле, что они не имеют экземпляров сами по себе — вместо этого их методы копируются (или «заимствуются») конкретными классами в качестве «наследования» поведения без вступления в формальные отношения с поставщиком поведения.
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 (иногда она называется augment). Обычно extend просто копирует (не не клонирует) функции примеси в принимающий объект. Быстрый обзор показывает несколько небольших вариаций этой реализации. Например, Prototype.js пропускает проверку hasOwnProperty (предполагается, что примесь не имеет перечислимых свойств в цепочке прототипов), тогда как другие версии исходят из того, что вы хотите скопировать только свойства из прототипа примеси. Вот безопасный и гибкий вариант…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.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.54this всегда указывает на получателя наборов функции, а не на абстрактный объект, который нам не нужен и который мы не используем; более того, в противоположность традиционному подходу, нам не нужна защита от непреднамеренного копирования унаследованных свойств, и (что бы это ни означало) функции теперь клонируются, а не копируются.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 с настраиваемыми параметрами grow и shrink: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 с добавлением кэширования… 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 с правильно каррированными функциями, позволяющими параметризацию grow и 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Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.
комментарии (39)