Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/413.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS函数和抽象类及原型_Javascript_Prototype - Fatal编程技术网

Javascript JS函数和抽象类及原型

Javascript JS函数和抽象类及原型,javascript,prototype,Javascript,Prototype,以下是我的代码的简化版本: function TextBox () { this.builddom = function () { // Building the text dom } } function ImageBox () { this.builddom = function () { // Building the image dom } } function Box (type) { var hand

以下是我的代码的简化版本:

  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,也可以,但是会破坏对Box的一般访问


我认为一些巧妙的原型操作可以完成这项工作,但我找不到它。

也许最好避免原型制作,而使用合成:

函数文本框(box){
this.builddom=function(){
console.log('构建文本dom',box.props);
}
}
功能图像框(框){
this.builddom=function(){
console.log('buildingtheimagedom',box.props);
}
}
功能盒(道具){
this.props=props;
this.builddom=function(){
抛出新错误(“不支持的函数”);
}
}
var textbox=new textbox(新框({size:5}));

builddom()如果您想使用原型,您可以这样:

功能文本框(道具){
this.props=props;
}
TextBox.prototype={
builddom:function(){
//构建文本dom
log(“TextBox”,this.props);
}
}
功能图像盒(道具){
this.props=props;
}
ImageBox.prototype={
builddom:function(){
//构建文本dom
log(“ImageBox”,this.props);
}
}
功能盒(类型、道具){
变量处理程序=(类型='text')?文本框:
(type=='Image')?ImageBox:null;
if(处理程序){
调用(这个,道具);
assign(这个,handler.prototype);
}
}
var textbox=新框('text',{text:'some'});
textbox.builddom();
var-imagebox=newbox('Image',{x:1,y:2});

imagebox.builddom()我真的不理解这个概念。这个盒子只是某种容器。它不做任何事情,而是创建一个新实例。这里您真正需要的是一个Box接口,但是js没有接口。如果您想

  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();

如果不打算使用box类,则无需创建它,而是创建一个工厂函数并返回相应类的新实例

函数AbstractBox(){}
AbstractBox.prototype.builddom=函数(){
console.warn(“未实现的方法”);
};
函数TextBox(){}
TextBox.prototype.builddom=函数(){
log(“调用TextBox.builddom”);
};
函数ImageBox(){}
ImageBox.prototype.builddom=函数(){
log(“调用ImageBox.builddom”);
};
函数ErrorBox(){}
函数createBox(类型){
var handler=Object.create(({
“文本”:文本框,
“图像”:ImageBox
}[类型]| |错误框)。原型);
handler.constructor.apply(handler,[].slice.call(参数,1));
for(AbstractBox.prototype中的var属性){
var方法=AbstractBox.prototype[属性];
if(typeof方法==“函数”&&&!(处理程序中的属性))处理程序[属性]=方法;
}
返回处理程序;
}
(createBox(“文本”)).builddom();//正文
(createBox(“图像”)).builddom();//形象

(createBox(“错误”)).builddom();//错误
不清楚为什么不在这里使用标准原型继承。它将允许您继承或重写父级的方法。例如,
ImageBox
继承父方法,而
TextBox
覆盖:

/*定义框*/
功能盒(类型){
this.type=type | |“box”
}
Box.prototype.builddom=函数(){
console.log(this.type,“:build called”)
}
/*定义文本框*/
函数文本框(){
框。调用(此“文本”)
}
TextBox.prototype=Object.create(Box.prototype);
/*覆盖方法*/
TextBox.prototype.builddom=函数(){
//也调用父方法?
//Box.prototype.builddom.call(this)
console.log(this.type,“文本框覆盖方法”)
}
/*定义图像框*/
函数ImageBox(){
框。调用(此“图像”)
}
ImageBox.prototype=Object.create(Box.prototype);
var-box=newbox();
builddom();
var textbox=新的textbox();
builddom();
var imageBox=新的imageBox();

builddom()我的建议是使用组合/委派而不是继承(has-a而不是is-a)


为什么不从其他两个函数扩展
Box
?这是一个非常奇怪的结构。您似乎希望创建
新框
返回从
文本框
图像框
继承的实例,这些实例基于
的参数。这是可能的,但坦率地说不是个好主意。@T.J.Crowder我完全同意。从任何抽象的角度来看,它都没有意义。在OOP中,您将使用委派ant实际直接传递
处理程序
,而不是传递
类型
,并试图在此基础上找出要使用的
处理程序
。或者,你会有一个某种工厂,返回不同的盒子。没有什么理由像现在这样使用
Box()。我要澄清一下。实际上,文本框和图像框不应该是我写的。Box函数是工具箱的一部分,其他开发人员应使用该约束创建xxxbox,以公开builddom方法(以及其他许多方法)。该工具包提供了某种盒子注册,以便能够使用这种新型盒子。这是在Java中使用“接口”或“抽象类”的完美例子。我最好使用JS'class'功能,但它还不能在所有浏览器中使用。很抱歉打断了评论,我没有意识到按Enter键会立即发送它。所以我所有的代码都只引用Box函数。ot
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 ();