在 kendo 中,使用原型繼承機制,Class 是 Kendo 中的基類,定義了函數 extend 用來派生其它類。
function Class() {}
Class.extend = function(proto) {
var base = function() {},
member,
that = this,
subclass = proto && proto.init ? proto.init : function () {
that.apply(this, arguments);
},
fn;
base.prototype = that.prototype;
fn = subclass.fn = subclass.prototype = new base();
for (member in proto) {
if (proto[member] != null && proto[member].constructor === Object) {
// Merge object members
fn[member] = extend(true, {}, base.prototype[member], proto[member]);
} else {
fn[member] = proto[member];
}
}
fn.constructor = subclass;
subclass.extend = that.extend;
return subclass;
};
首先,我們可以看到
function Class() {}
也就是說,Class 是一個函數,在 Kendo 中,所有的類都是通過函數定義,建立對象使用 new 方式來建立。
Class.extend = function(proto) {
這裡的 extend 是 Class 的靜态成員,在 Kendo 中,派生子類都是通過父類的 extend 方式進行處理。方法的參數是子類所擴充的成員對象。
在這個函數内部,首先定義了一個基類函數 base,這顯得很奇怪,但是,很快可以發現,這個函數的原型與 Base 的原型其實是同一個,是以通過它們建立出來的對象,行為模式其實是相同的。
var base = function() {},
subclass = proto && proto.init ? proto.init : function () {
that.apply(this, arguments);
},
base.prototype = that.prototype;
fn = subclass.fn = subclass.prototype = new base();
而子類則為 init 函數所定義,在 new 子類對象執行個體的時候,實際上調用的就是定義子類時提供的 init 函數,在子類的 init 函數内部又調用了父類的構造函數,實作繼承機制。
通過将子類的原型設定為父類的對象執行個體,實作原型繼承機制。
子類總是會擴充父類的成員,下面的代碼實作為子類的原型對象擴充各種成員。
for (member in proto) {
if (proto[member] != null && proto[member].constructor === Object) {
// Merge object members
fn[member] = extend(true, {}, base.prototype[member], proto[member]);
} else {
fn[member] = proto[member];
}
}
constructor屬性始終指向建立目前對象的構造函數。這裡将原型對象的建構函數也設定為子類函數。保證檢查類型的時候可以正确工作,可以參看這裡的說明:JavaScript:constructor屬性
fn.constructor = subclass;
使子類也擁有一個同樣的 extend 函數,便于繼續派生子類。
subclass.extend = that.extend;