Ext源代码阅读-001
基于V3.03 Ext.extend阅读注释:
代码如下:
extend : function(){
//内联属性复制(继承)
var io = function(o){
for(var m in o){
this[m] = o[m];
}
};
var oc = Object.prototype.constructor;//javascript基对象构造函数
//参数说明:
//sb:父类构造函数
//sp:子类需要扩展的属性
//overrides:在sp类型为Object时没用
//本函数的妙处在于闭包的应用,在闭包内的各种变量都将保留以备后用
//以下的分析基于sp参数为自定义对象的情况
return function(sb, sp, overrides){
if(Ext.isObject(sp)){//子类扩展的属性以自定义对象形式传入
overrides = sp;//保存子类扩展
sp = sb;//执行后sp实际上就是父类构造函数了
//如下代码是关键:
//sp.apply(this, arguments)里此处arguments是new对象时的构造参数,比如new xxx('p')里的参数p
//从下面代码可以看出子类构造函数有两种形式返回:
//1.子类扩展自定义构造函数(overrides.constructor),这样本函数执行以后返回的就是用户自己定义的
//构造函数
//2.如果子类扩展没有定义构造函数,则以 function(){sp.apply(this, arguments) 返回,这里sp就是父类构造
//函数,这样在执行(new 子类)的时候子类构造就会执行父类构造(通过sp.apply(this, arguments)
//这样如果有一颗继承树的话,构造的执行将是:子类构造->调用父类构造->调用父父类构造....,一直到所有
//父类构造执行完毕
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
}
var F = function(){},
sbp,
spp = sp.prototype;//父类的原型属性
F.prototype = spp;
sbp = sb.prototype = new F();//继承父类原型属性就在这里实现了
sbp.constructor=sb;//纠正constructor指向(javascript每个函数的prototype.constructor应该都是指向自己的)
sb.superclass=spp;
if(spp.constructor == oc){
spp.constructor=sp;
}
//最后定义两个类方法override和extend以备方便使用
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;
};
}()
最后的()必不可少,如果少了,则执行Ext.extend(父类,子类属性)进行扩展时实际上没有执行函数体return function(sb, sp, overrides)内的扩展操作
实际上Ext.extend只能达到继承原型属性的目的,如果需要继承动态属性,比如下面的示例:
var mypf=function()
{
//该构造将被子类构造调用(通过sp.apply(this, arguments)
this.x=100;//这里x是无法继承到子类的
}
//原型可以直接继承
mypf.prototype.show=function(){
alert('mypf');
}
//扩展mypf
var myc=Ext.extend(
mypf,
{
y:10,
testme:function(){
alert('haha');
}
//,//这里可以定义自己的构造函数
//constructor:function(){}
}
);//这时myc中还没有mypf的x实例属性
var myci=new myc();//这里执行以后myci中就有mypf的x实例属性了,这里可以在构造时传入参数,这些参数将反映在sp.apply(this, arguments)中的arguments中,进而可以在父类构造中使用
根据上面的分析,父类构造将在子类实例化的时候被子类构造调用,所以这里的this.x是在(new 子类)的时候间接调用父类构造而实现的
代码如下:
extend : function(){
//内联属性复制(继承)
var io = function(o){
for(var m in o){
this[m] = o[m];
}
};
var oc = Object.prototype.constructor;//javascript基对象构造函数
//参数说明:
//sb:父类构造函数
//sp:子类需要扩展的属性
//overrides:在sp类型为Object时没用
//本函数的妙处在于闭包的应用,在闭包内的各种变量都将保留以备后用
//以下的分析基于sp参数为自定义对象的情况
return function(sb, sp, overrides){
if(Ext.isObject(sp)){//子类扩展的属性以自定义对象形式传入
overrides = sp;//保存子类扩展
sp = sb;//执行后sp实际上就是父类构造函数了
//如下代码是关键:
//sp.apply(this, arguments)里此处arguments是new对象时的构造参数,比如new xxx('p')里的参数p
//从下面代码可以看出子类构造函数有两种形式返回:
//1.子类扩展自定义构造函数(overrides.constructor),这样本函数执行以后返回的就是用户自己定义的
//构造函数
//2.如果子类扩展没有定义构造函数,则以 function(){sp.apply(this, arguments) 返回,这里sp就是父类构造
//函数,这样在执行(new 子类)的时候子类构造就会执行父类构造(通过sp.apply(this, arguments)
//这样如果有一颗继承树的话,构造的执行将是:子类构造->调用父类构造->调用父父类构造....,一直到所有
//父类构造执行完毕
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
}
var F = function(){},
sbp,
spp = sp.prototype;//父类的原型属性
F.prototype = spp;
sbp = sb.prototype = new F();//继承父类原型属性就在这里实现了
sbp.constructor=sb;//纠正constructor指向(javascript每个函数的prototype.constructor应该都是指向自己的)
sb.superclass=spp;
if(spp.constructor == oc){
spp.constructor=sp;
}
//最后定义两个类方法override和extend以备方便使用
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;
};
}()
最后的()必不可少,如果少了,则执行Ext.extend(父类,子类属性)进行扩展时实际上没有执行函数体return function(sb, sp, overrides)内的扩展操作
实际上Ext.extend只能达到继承原型属性的目的,如果需要继承动态属性,比如下面的示例:
var mypf=function()
{
//该构造将被子类构造调用(通过sp.apply(this, arguments)
this.x=100;//这里x是无法继承到子类的
}
//原型可以直接继承
mypf.prototype.show=function(){
alert('mypf');
}
//扩展mypf
var myc=Ext.extend(
mypf,
{
y:10,
testme:function(){
alert('haha');
}
//,//这里可以定义自己的构造函数
//constructor:function(){}
}
);//这时myc中还没有mypf的x实例属性
var myci=new myc();//这里执行以后myci中就有mypf的x实例属性了,这里可以在构造时传入参数,这些参数将反映在sp.apply(this, arguments)中的arguments中,进而可以在父类构造中使用
根据上面的分析,父类构造将在子类实例化的时候被子类构造调用,所以这里的this.x是在(new 子类)的时候间接调用父类构造而实现的