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的實現場景。