2

如果我为我的对象使用构造函数并为共享功能使用原型,我想将共享功能(函数)混合到对象的原型中,但将实例特定(this变量)混合到对象实例中。

要添加原型部分,我发现了这种模式。为了设置原型函数假定存在的实例变量,我想出了一个 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函数假定存在的初始实例变量?

4

1 回答 1

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();
于 2013-07-23T17:27:36.130 回答