Javascript原型继承与多个对象

时间:2014-11-06 16:17:10

标签: javascript prototypal-inheritance

说我有5个物体

Callback
Perishable
Object1
Object2
Object3

Object1需要扩展Callback而不是Perishable对象,而Object 2应该扩展两者,而Object 3应该扩展Perishable而不是回调。

我知道这有效......

Object1.prototype = new Callback();
Object3.prototype = new Perishable();

但我怎么做(我知道这不起作用)

Object2.prototype = new Callback() && new Perishable();

3 个答案:

答案 0 :(得分:2)

您可以使用extend function from Underscore.js library

代码如下所示:

_.extend(Object1.prototype, Callback.prototype);
_.extend(Object1.prototype, Perishable.prototype);

这里的JS小提琴:http://jsfiddle.net/yb7kkh4e/2/

答案 1 :(得分:2)

如果您不想要任何外部依赖项,可以使用extend

的此实现
function __extends(d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    var a = function(){}; a.prototype = new b();
    for (var p in a.prototype) d.prototype[p] = a.prototype[p];   
};

示例:

var animal = function(){

};

animal.prototype.run = function(){
     console.log("running");   
};

var feline = function(){

};

feline.prototype.hunt = function(){
     console.log("hunting");   
};

var cat = function(){

};

__extends(cat, animal);
__extends(cat, feline);

var scaryCat = new cat();

scaryCat.run();

scaryCat.hunt();

小提琴:http://jsfiddle.net/apqwf93a/9/

答案 2 :(得分:1)

通常,当您想要扩展多个对象时,您必须查看您的设计是否正确。对象是另一个对象吗?

例如,猫是动物,猫可以移动。从Catable扩展Cat是错误的,因为Cat不是Movable它可以移动所以它应该实现Movable或保留Movable的默认实现。

Cat Feline and Animal的例子很好,但可以在没有多重继承的情况下解决。猫是猫科动物,猫科动物是动物,所以没有理由让猫继承猫科动物和动物,你可以让猫继承猫科动物的猫科动物和猫科动物。

所选答案涉及mix ins(implements)的原型部分,但不包括如何初始化特定于实例的成员。以下是following answer的部分内容:

使用混合输入的多重继承

如果猫可以移动而且猫不应该从Movable继承,有些事情最好不要继承。猫不是可移动的,而是猫可以移动。在基于类的语言中,Cat必须实现Movable。在JavaScript中我们可以在这里定义Movable并定义实现,Cat可以覆盖,扩展它或者我们的默认实现。

对于Movable,我们有特定于实例的成员(如location)。我们的成员不是特定于实例的(如函数move())。在创建实例时,将通过调用mxIns(由mixin helper函数添加)来设置特定于实例的成员。原型成员将使用mixin辅助函数从Movable.prototype中逐个复制到Cat.prototype上。

var Mixin = function Mixin(args){
  var i, len;
  if(this.mixIns){
    i=-1;len=this.mixIns.length;
    while(++i<len){
        this.mixIns[i].call(this,args);
      }
  }  
};
Mixin.mix = function(constructor, mix){
  var thing
  ,cProto=constructor.prototype
  ,mProto=mix.prototype;
  //no extending, if multiple prototype uhs
  // have members with the same name then use
  // the last
  for(thing in mProto){
    if(Object.hasOwnProperty.call(mProto, thing)){
      cProto[thing]=mProto[thing];
    }
  }
  //instance intialisers
  cProto.mixIns = cProto.mixIns || [];
  cProto.mixIns.push(mix);
};
var Movable = function(args){
  args=args || {};
  //demo how to set defaults with truthy
  // not checking validaty
  this.location=args.location;
  this.isStuck = (args.isStuck===true);//defaults to false
  this.canMove = (args.canMove!==false);//defaults to true
  //speed defaults to 4
  this.speed = (args.speed===0)?0:(args.speed || 4);
};
Movable.prototype.move=function(){
  console.log('I am moving, default implementation.');
};
var Animal = function(args){
  args = args || {};
  this.name = args.name || "thing";
};
var Cat = function(args){
  Animal.call(args);
  //if an object can have others mixed in
  //  then this is needed to initialise 
  //  instance members
  Mixin.call(this,args);
};
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Mixin.mix(Cat,Movable);
var poochie = new Cat({
  name:"poochie",
  location: {x:0,y:22}
});
poochie.move();