犀利的继承-再看Ext.extend
2012-02-02 23:20 尔 阅读(158) 评论(0) 收藏 举报忽然在一个旮旯出看见一个高人对Ext.entend有一句相当犀利的总结--Ext.extend统一了实现接口(抽象类)和继承类。
自己分析如下。
严格来说js没有类更加没有接口,这里的类和接口只是一种功能上的近似。
比如,在Ext里,想让一个自定义的类具有“添加事件的能力”,会继承Observable,从名称上看就知道Observable是一个“接口(伪)”,此时,自定义的类和Observable之间没有明显的继承关系,只是让自定义的类具有Observable的“能力”而已,此时可以称之为实现接口(抽象类)。
在严格的继承关系中,子类的构造是依赖于父类的构造的,Ext.extend也是这么做的,当走“继承”这条分支时,Ext.entend返回的是一个构造函数,而且此时构造函数是构造于父类的构造函数之上的。
Ext.extend它是如何区别你要走“继承类”路线,还是“实现接口”路线呢?
关键就是你传入第二个参数的类型。
sb(子类)sp(父类),sbp(子类的原型),spp(父类的原型)
一个典型的闭包场景,立即执行的匿名函数,实际使用的其实是,return function(sb, sp, overrides)
oc,io对外不可见
源码如下
extend : function(){
var io = function(o){
for(var m in o){
this[m] = o[m];
}
};
//oc指向Object的构造函数
var oc = Object.prototype.constructor;
//如果第二个参数是js对象,那么走继承类路线
//返回子类的构造函数
return function(sb, sp, overrides){
//经典一
//继承类的路线
//sb(子类),sp(父类),
//参数的位置变换
if(Ext.isObject(sp)){
//参数后移一位
overrides = sp;
sp = sb;
//sb被重新定义为父类的构造函数 (给子类一个默认的构造函数)
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
}
//经典二
//空壳函数,为了只得到父类原型而剔除那些通过this绑定的值,
//当继承后,
//sb.superclass.constructor.call(this,config),父类构造函数
//已经在子类构造函数里重新被call(父类this绑定的属性重新被子类this 绑定)
//继承后,父类的实例属性成为子类的原型属性
//此时成为子类原型中属性,已是多余
var F = function(){},
sbp,
spp = sp.prototype;
//典型的继承
F.prototype = spp;
sbp = sb.prototype = new F();
sbp.constructor=sb;
sb.superclass=spp;
//容错处理
if(spp.constructor == oc){
spp.constructor=sp;
}
//给子类添加override函数
sb.override = function(o){
Ext.override(sb, o);
};
sbp.superclass = sbp.supr = (function(){
return spp;
});
sbp.override = io;
//复制第二个参数到第一个参数原型对象上
Ext.override(sb, overrides);
sb.extend = function(o){return Ext.extend(sb, o);};
return sb;
};
}(),
浙公网安备 33010602011771号