JS 继承:extend、mixin 和 plugin(二)


Mixin:

Mixin 是一种JS实现多继承方式,它通过复制其他类原型链(prototype)上的方法到自身原型链(prototype)上,来实现多继承。根据定义我们可以实现函数:

 /**

  * 将其他类作为mixin集成到指定类上面

  * @param {Function} c 构造函数

  * @param {Array} mixins 扩展类

  * @return {Function} 传入的构造函数

  */

function mixin(c,mixins){

  var prototype = c.prototype;

  $.each(mixins, function (index,ext) {

if (ext) {

var proto = ext.prototype;

for (var p in proto) {

prototype[p] = proto[p];

}

}

});

return c;

}

有了这个方法,我们来做一下实验:

  

function A(){};

A.prototype = {

method:function(){

return 'a';

},

methodA:function(){

}

};

function B(){};

B.prototype = {

method:function(){

return 'b';

},

methodB:function(){

}

};

function C(){}

C.prototype = {

method:function(){

return 'c';

},

methodC:function(){

}

};

mixin(C,[A,B]);

var c = new C();

alert(c.method()); //输出 b

此时我们看到结果是b但是根据继承的定义,子类的方法覆盖父类,所以这个结果不是我们想要的。我们需要子类的方法覆盖minxins 的方法。那么我们继续更改:

function mixin(c,mixins){

var prototype = {},

   constructors = mixins['concat'](c);

$.each(constructors , function (index,ext) {

if (ext) {

var proto = ext.prototype;

for (var p in proto) {

prototype[p] = proto[p];

}

}

});

$.each(prototype, function (k,v) {

    c.prototype[k] = v;

});

return c;

}

此时再执行上面的结果,

var c = new C();

alert(c.method()); //输出 c

看上去现在mixin我们完整的实现了,但是如果C本来继承了Base类,而Base类又有方法跟mixins中的类的方法重复,我们怎么办:

function Base(){}

Base.prototype = {

method:function(){

return 'base';

},

methodA:function(){

  return 'base';

}

};

function C(){

}

extend(C,Base);

C.prototype.method = function(){

return c

}

mixin(C,[A,B]);

var c = new C();

alert(c.method()); //输出 c

alert(c.methodA()); //输出 base

但是从继承的概念上讲,Base没有继承mixins中的方法,所以C从minxins中继承来的方法的优先级应该高于Base类中的方法,所以我们需要覆盖父类的方法,那么我们minxin 的最终版本是:

function mixin(c,mixins){

var prototype = {},

   constructors = mixins['concat'](c);

$.each(constructors , function (index,ext) {

if (ext) {

var proto = ext.prototype;

for (var p in proto) {

//由于本身的构造函数在最后面,父类的方法不覆盖mixins中的方法

if (proto.hasOwnProperty(p)) {

             prototype[p] = proto[p];

           }

}

}

});

$.each(prototype, function (k,v) {

    c.prototype[k] = v;

});

return c;

}

小结:

Mixin 在实现JS的继承是一种非常强大的方式,特别是写控件时,可以将大量抽象的逻辑封装成一个个的mixin,我们在实现一个控件时,可以将这些mixins直接引入控件类上,不需要重新编写实现。后面我会讲解一些常见的mixin。

下一节我会讲解plugin ,同时对比plugin 跟 mixin的实现场景。

posted @ 2012-10-22 00:18  zaohe  阅读(7795)  评论(1编辑  收藏  举报