这是我的代码的简化版:
function TextBox () {
this.builddom = function () {
// Building the text dom
}
}
function ImageBox () {
this.builddom = function () {
// Building the image dom
}
}
function Box (type) {
var handler =
(type == 'text') TextBox :
(type == 'Image') ImageBox : null;
if (handler) (handler).call (this);
this.builddom = function () {
// Here I would like to call the correct builddom function for the type.
}
}
var textbox = new Box ('text');
textbox.builddom ();
如果Box.builddom不存在,则工作正常,将调用与特定类型关联的builddom函数。但是我需要在Box中做一些常规的事情,然后调用特定的builddom。如果我为Box builddom命名为Box.dobuilddom,它也可以,但是会破坏对Boxes的通用访问。
我认为可以通过一些巧妙的原型操作来完成这项工作,但是我找不到它。
答案 0 :(得分:2)
也许最好避免原型设计,而使用合成:
function TextBox(box) {
this.builddom = function() {
console.log('Building the text dom', box.props);
}
}
function ImageBox(box) {
this.builddom = function() {
console.log('Building the image dom', box.props);
}
}
function Box(props) {
this.props = props;
this.builddom = function() {
throw new Error('unsupported function');
}
}
var textbox = new TextBox(new Box({size:5}));
textbox.builddom();
答案 1 :(得分:1)
我不太了解这个概念。盒子只是某种容器。它不执行任何操作,而是创建一个新实例。您真正需要的是Box接口,但是js没有接口。您可以使用TypeScript ...
function TextBox () {
this.builddom = function () {
// Building the text dom
}
}
function ImageBox () {
this.builddom = function () {
// Building the image dom
}
}
var container = {
createBox: function (type){
if (type == "text")
return new TextBox();
else if (type == "image")
return new ImageBox();
else
throw new Error();
}
};
var textbox = container.createBox('text');
textbox.builddom();
如果您想包装对象,另一个选择是使用代理,但我认为这不是您的目标。
如果以后需要类型检查,则可以使用继承,但是没有多重继承,因此即使那样,您也无法模仿接口。顺便说一句。
function Box (){}
function TextBox () {}
TextBox.prototype = Object.create(Box.prototype, {
constructor:TextBox,
builddom: function () {
// Building the text dom
}
});
function ImageBox () {}
ImageBox.prototype = Object.create(Box.prototype, {
constructor:ImageBox,
builddom: function () {
// Building the image dom
}
});
var container = {
createBox: function (type){
if (type == "text")
return new TextBox();
else if (type == "image")
return new ImageBox();
else
throw new Error();
}
};
var textbox = container.createBox('text');
console.log(
textbox instanceof Box,
textbox instanceof ImageBox,
textbox instanceof TextBox
);
textbox.builddom();
答案 2 :(得分:0)
如果您想使用原型,可以像这样:
function TextBox(props) {
this.props = props;
}
TextBox.prototype = {
builddom: function () {
// Building the text dom
console.log("TextBox", this.props);
}
}
function ImageBox(props) {
this.props = props;
}
ImageBox.prototype = {
builddom: function () {
// Building the text dom
console.log("ImageBox", this.props);
}
}
function Box (type, props) {
var handler = (type == 'text') ? TextBox :
(type == 'Image') ? ImageBox : null;
if (handler) {
handler.call(this, props);
Object.assign(this, handler.prototype);
}
}
var textbox = new Box ('text', {text: 'some'});
textbox.builddom ();
var imagebox = new Box ('Image', {x: 1, y: 2});
imagebox.builddom ();
答案 3 :(得分:0)
如果您不想使用Box类,则无需创建它,而是创建一个工厂函数并返回相应类的新实例。
function AbstractBox() {}
AbstractBox.prototype.builddom = function() {
console.warn("unimplemented method");
};
function TextBox() {}
TextBox.prototype.builddom = function() {
console.log("TextBox.builddom called");
};
function ImageBox() {}
ImageBox.prototype.builddom = function() {
console.log("ImageBox.builddom called");
};
function ErrorBox() {}
function createBox(type) {
var handler = Object.create(({
"text": TextBox,
"Image": ImageBox
}[type] || ErrorBox).prototype);
handler.constructor.apply(handler, [].slice.call(arguments, 1));
for (var property in AbstractBox.prototype) {
var method = AbstractBox.prototype[property];
if (typeof method === "function" && !(property in handler)) handler[property] = method;
}
return handler;
}
(createBox("text")).builddom(); // Text
(createBox("Image")).builddom(); // Image
(createBox("error")).builddom(); // Error
答案 4 :(得分:0)
目前尚不清楚为什么不只在这里使用标准原型继承。它将允许您继承或重写父方法。例如,ImageBox
继承父方法,而TextBox
覆盖:
/* Define Box */
function Box (type) {
this.type = type || 'box'
}
Box.prototype.builddom = function (){
console.log(this.type, ": build called")
}
/* Define TextBox */
function TextBox () {
Box.call(this, "text")
}
TextBox.prototype = Object.create(Box.prototype);
/* Override method */
TextBox.prototype.builddom = function (){
// call parent method too?
// Box.prototype.builddom.call(this)
console.log(this.type, "Text box override method")
}
/* Define ImageBox */
function ImageBox () {
Box.call(this, "image")
}
ImageBox.prototype = Object.create(Box.prototype);
var box = new Box ();
box.builddom();
var textbox = new TextBox ();
textbox.builddom();
var imageBox = new ImageBox ();
imageBox.builddom();
答案 5 :(得分:0)
我的建议是使用组合/委托而不是继承(用-a代替is-a)。
function TextBox () {
this.builddom = function () {
// Building the text dom
}
}
function ImageBox () {
this.builddom = function () {
// Building the image dom
}
}
function Box (type) {
var constructor =
(type == 'text') ? TextBox :
(type == 'Image') ? ImageBox : null;
var delegate = new constructor();
this.builddom = function () {
// Pre-work goes here.
delegate.builddom();
// Post-work goes here.
}
}
var textbox = new Box ('text');
textbox.builddom ();