具有多个对象的Javascript原型继承
Javascript Prototypal inheritance with Multiple Objects
假设我有5个对象
Callback
Perishable
Object1
Object2
Object3
对象1需要扩展回调,而不是Perishable对象,而对象2应该同时扩展这两个对象,对象3应该扩展Perishable,而不是回调。
我知道这很管用。。。
Object1.prototype = new Callback();
Object3.prototype = new Perishable();
但是我该怎么做像这样的事情呢
Object2.prototype = new Callback() && new Perishable();
如果您不想要任何外部依赖项,可以使用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();
Fiddle:http://jsfiddle.net/apqwf93a/9/
您可以使用Underscore.js库中的扩展函数。
代码如下所示:
_.extend(Object1.prototype, Callback.prototype);
_.extend(Object1.prototype, Perishable.prototype);
这是JS fiddle:http://jsfiddle.net/yb7kkh4e/2/
通常,当您想要扩展多个对象时,您必须检查您的设计是否正确。这个物体是另一个物体吗?
例如,猫是动物,猫可以移动。从Movable扩展Cat是错误的,因为Cat不是Movable,它可以移动,所以它应该实现Movable或保留默认的Movable实现。
猫-猫和动物的例子很好,但可以在没有多重继承的情况下解决。猫是猫科动物,猫科动物是动物,所以没有理由让猫既继承猫科动物,也继承动物,你可以让猫继承猫科动物和猫科动物。
所选择的答案涉及mix-ins(实现)的原型部分,但不涉及如何初始化实例特定的成员。以下是以下答案的一部分:
具有混合ins的多重继承
有些东西最好不要继承,如果猫可以移动,而猫不应该从移动继承。猫不是可移动的,而是可以移动的。在基于类的语言中,Cat必须实现Movable。在JavaScript中,我们可以在这里定义Movable和定义实现,Cat可以覆盖、扩展它,也可以我们它的默认实现。
对于Moveable,我们有特定于实例的成员(如location
)。我们有一些成员不是特定于实例的(比如函数move())。在创建实例时,将通过调用mxIns(由mixin-helper函数添加)来设置实例特定的成员。原型成员将使用mixin-helper函数在Cat.Prototype上从Movable.protype逐个复制。
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();
- 使用“;这个“;JavaScript原型方法中的关键字
- Node.js中的JavaScript原型对象效率
- 为什么要返回'这'在导致循环的JavaScript原型中
- JavaScript原型设计基础知识
- 就良好实践而言,带闭包的javascript原型是一件好事吗
- 无法从angularjs调用JavaScript原型函数
- JavaScript原型示例
- Javascript原型组织
- 未复制JavaScript原型
- JavaScript原型的意义到底是什么
- 两个对象之间的Javascript原型
- 使用特权Getter/Setter函数的JavaScript原型函数
- 语法错误,但无法调试JavaScript原型
- 澄清:Javascript原型更新混乱
- 如何进行JavaScript原型继承(原型链)
- Javascript原型通用Enquries和通过数组索引分配Id
- 理解Javascript原型继承
- JavaScript原型与实践中的对比
- JavaScript原型构造函数只调用过一次
- Javascript原型继承原型函数调用