如果我使用构造函数用于我的对象和原型用于共享功能,我想将共享功能(函数)混合到对象的原型,但是特定于实例(this
变量)到对象实例。
要添加原型部件,我找到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函数假设的初始实例变量?
答案 0 :(得分: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();