2013-07-22 46 views
2

如果我使用我的对象的构造函数和共享功能的原型,我想将对象的原型的共享功能(函数)混合到对象实例中,但实例特定(this变量)。Javascript mixin模式设置实例特定于此变量

要添加原型部分,我发现this pattern。为了设置原型函数假定存在的实例变量,我想出了一个init(每个mixin一个)。

下面是一个简单的例子:

var mixIn=function(target,source){ 
    for(fn in source){ 
    if(source.hasOwnProperty(fn)){ 
     target.prototype[fn]=source[fn]; 
    } 
    } 
}; 
var SpeakEnable = { 
    say:function(){ 
    console.log(this.message); 
    }, 
    initSpeak:function(){// for initializing instance vars 
    this.message="Hello World Mixed in!"; 
    this.object=[]; 
    } 
}; 
var Person=function(){ 
    this.initSpeak();//have to init instance vars 
}; 
// set up inheritance 
// set up Person.prototype 
// set speak enable 
mixIn(Person,SpeakEnable); 

var lulu=new Person(); 
lulu.say(); 

var june=new Person(); 
console.log(june.say===lulu.say);//true 
console.log(june.object===lulu.object);//false 

这一切工作正常,很正常,但在初始化实例变量是在那里我有一些问题。它似乎不是一个非常干净的方式。当我混合使用多个mixin时,Person构造函数必须调用所有init函数来设置实例变量。忘记调用它会导致奇怪的错误(在这种情况下,在实例上调用say时,控制台日志记录未定义)。

所以问题是:是否有一种更简洁的方式来设置初始实例变量,这些变量被认为是由mixin函数存在的?

回答

1

您可以从基础对象继承所有可混合的对象,以确保正确的初始化。这是实现您的目标的干净方式。

下面的代码演示了这个原则:

//------------ framework 

var inherits = function(childCtor, parentCtor) { 
    function tempCtor() {}; 
    tempCtor.prototype = parentCtor.prototype; 
    childCtor.superClass_ = parentCtor.prototype; 
    childCtor.prototype = new tempCtor(); 
    childCtor.prototype.constructor = childCtor; 
}; 

var mixIn=function(target,source){ 
    for(fn in source){ 
    if(source.hasOwnProperty(fn) && fn.name != 'init'){ 
     target.prototype[fn]=source[fn]; 
    } 
    } 

    if (typeof source.init == 'function') { 
     if (target.prototype._mixInits === undefined) { 
      target.prototype._mixInits = []; 
     } 
     target.prototype._mixInits.push(source.init); 
    } 
}; 

// all objects that can be mixin's should inherit from 
// this object in order to ensure proper initialization 
var Mixable = function() { 
    var mixInits = this.__proto__._mixInits; 
    if (mixInits !== undefined) { 
     for (var i = 0; i < mixInits.length; i++) { 
      mixInits[i].call(this); 
     } 
    } 
}; 

//------------ testcode 

var SpeakEnable = { 
    say:function(){ 
    console.log(this.message); 
    }, 
    init:function(){ 
    console.log('say init called'); 
    this.message="Saying Hello World Mixed in!"; 
    this.object=[]; 
    } 
}; 

var WalkEnable = { 
    walk:function(){ 
    console.log(this.walk_message); 
    }, 
    init:function(){ 
    console.log('walk init called'); 
    this.walk_message="Walking step 1.2.3."; 
    } 
}; 


var Person=function() { 
    Mixable.call(this); 
}; 

inherits(Person, Mixable); 

mixIn(Person,SpeakEnable); 
mixIn(Person,WalkEnable); 

var lulu=new Person(); 
lulu.say(); 
lulu.walk(); 
+0

谢谢你,你可以删除inherrit因为'Mixable.call(这)'足以初始化实例。 – HMR

+0

是的。不过,我会考虑这个适当的设计。您也可以将其用作检查mixIn是否可行(即,在mixIn函数中,您将检查目标是否从Mixable继承)。确实,这仍然不能保证超级的构造函数被调用,但它是多余的。 –