extend : function(){
// inline overrides
var io = function(o){
for(var m in o){
this[m] = o[m];
}
};
var oc = Object.prototype.constructor;
return function(sb, sp, overrides){
//判断第二个参数为object时,就是判断是否传入的是二个参数
if(Ext.isObject(sp)){
overrides = sp;//overides是第二个参数了(对象类型)
//sp是第一个参数了
sp = sb;
//sb是一个构造函数了
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
}
var F = function(){},
sbp,
spp = sp.prototype;
//用F代替超类,目的是改变sb的prototype不会改变sp的prototype
F.prototype = spp;
//下面2行,就如上面的例子一样,很典型的js继承方式
sbp = sb.prototype = new F();
sbp.constructor=sb;
//给子类添加一个属性,方便指回父类的原型对象
sb.superclass=spp;
if(spp.constructor == oc){
spp.constructor=sp;
}
//给sb添加override静态方法
sb.override = function(o){
Ext.override(sb, o);
};
sbp.superclass = sbp.supr = (function(){
return spp;
});
//给子类添加override实例方法
sbp.override = io;
Ext.override(sb, overrides);
//为sb添加静态方法
sb.extend = function(o){Ext.extend(sb, o);};
return sb;
};
}(),
接着上回笔记。
Ext.extend()这个函数看了近4个小时才感觉明白了个大概其,一个原因是自己功力不够,另一个原因是Jack Slocum这个函数写得确实是吊。
复习一下js的继承吧。
js其实并不是标准的面向对象语言,它只是模拟继承,方法多种多样,非常复杂。
一般js实现OO方式的继承,是重写子类的prototype,让父类的实例成为子类的prototype对象,那么这个子类就有父类的实例属性,而这个父类的实例同时又有_proto_指向自己的prototype对象,那么也就是说,这个子类也就间接有了父类prototype对象里的属性。
注意是间接的方式:SubClass.prototype---->superInstance,superInstance._proto_---->SuperClass.prototype
由于子类的prototype对象现在指向了父类的prototype对象,所以constructor此时指向了父类的构造函数,这当然不是符合逻辑的,所以还要把constrctor重新指回子类的构造函数。
Ext实际是用的下面这种继承方式
一个例子:
function Sup(name){
this.name=name;
}
Sup.prototype.fn=function(){
alert("父类原型中方法")
}
function Sub(age){
Sup.call(this);//防止一个类的不同实例共享属性,也就是不要把从父类继承的属性放到prototype对象里,用对象的反射调用(this,用特定的上下文调用父类的构造函数,引入其属性),就可以解决 这个问题
this.age=age;
}
EXT其实是提供了2中继承的方式。
1,对象的继承。(Ext.apply)
其实就是把父对象的属性方法复制到子对象中。
2,类的继承。(Ext.extend)
把父类的属性或方法复制到子类的原型对象中。
OK了,看会EXT的源码把
再次感叹,这个函数,写得确实很有水平。
首先,它是一个立即执行的函数,返回其中的闭包,这样可以提高效率和保证期变量的私有性。
其实,我们实际使用的function(sb, sp, overrides)这个函数。
其次,这个函数有俩种方式调用。
1,二个参数版本(第一个参数:函数类型,第二个参数:对象类型)
2,三个参数版本(第一个 参数:子类,第二个参数:父类,第三个参数:对象类型)
理解,写在注解中。
extend : function(){
// inline overrides
var io = function(o){
for(var m in o){
this[m] = o[m];
}
};
var oc = Object.prototype.constructor;
return function(sb, sp, overrides){
//判断第二个参数为object时,就是判断是否传入的是二个参数
if(Ext.isObject(sp)){
overrides = sp;//overides是第二个参数了(对象类型)
//sp是第一个参数了
sp = sb;
//sb是一个构造函数了
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
}
var F = function(){},
sbp,
spp = sp.prototype;
//用F代替超类,目的是改变sb的prototype不会改变sp的prototype
F.prototype = spp;
//下面2行,就如上面的例子一样,很典型的js继承方式
sbp = sb.prototype = new F();
sbp.constructor=sb;
//给子类添加一个属性,方便指回父类的原型对象
sb.superclass=spp;
if(spp.constructor == oc){
spp.constructor=sp;
}
//给sb添加override静态方法
sb.override = function(o){
Ext.override(sb, o);
};
sbp.superclass = sbp.supr = (function(){
return spp;
});
//给子类添加override实例方法
sbp.override = io;
Ext.override(sb, overrides);
//为sb添加静态方法
sb.extend = function(o){Ext.extend(sb, o);};
return sb;
};
}(),