zl程序教程

您现在的位置是:首页 >  后端

当前栏目

js继承Base类的源码解析

JS源码继承 解析 base
2023-06-13 09:14:07 时间
//timestamp:Tue,01May200719:13:00
/*
base2.js-copyright2007,DeanEdwards
http://www.opensource.org/licenses/mit-license
*/
//Youknow,writingajavascriptlibraryisawfullytimeconsuming.
////////////////////BEGIN:CLOSURE////////////////////
//=========================================================================
//base2/Base.js
//=========================================================================
//version1.1
varBase=function(){
//callthismethodfromanyothermethodtoinvokethatmethod"sancestor
};
Base.prototype={
extend:function(source){
//参数大于一个时
if(arguments.length>1){//extendingwithaname/valuepair
//获得proto的祖先
varancestor=this[source];
varvalue=arguments[1];
//如果value(第二个参数)是function,并且祖先对象存在,在重载函数中调用base时
if(typeofvalue=="function"&&ancestor&&/\bbase\b/.test(value)){
//gettheunderlyingmethod
varmethod=value;
//override
value=function(){
varprevious=this.base;
this.base=ancestor;
//上溯到父类对象
varreturnValue=method.apply(this,arguments);
this.base=previous;
returnreturnValue;
};
value.method=method;
value.ancestor=ancestor;
}
this[source]=value;
}
else
if(source){//extendingwithanobjectliteral用一个对象列表来扩展
varextend=Base.prototype.extend;
/**
*1.扩展原型方法和属性2.
*/
//如果是扩展属于原型的方法或属性,先遍历其重载Object的3个方法
if(Base._prototyping){
varkey,i=0,members=["constructor","toString","valueOf"];
while(key=members[i++]){
//如果是重载了这些方法
if(source[key]!=Object.prototype[key]){
/**
*逐个扩展,用call的原因是要将extend的上下文改为要扩展的源this,
*既是新建对象的父类对象
*/
extend.call(this,key,source[key]);
}
}
}
else
if(typeofthis!="function"){
//iftheobjecthasacustomisedextend()methodthenuseit
extend=this.extend||extend;
}
//copyeachofthesourceobject"spropertiestothisobject
for(keyinsource)
if(!Object.prototype[key]){
extend.call(this,key,source[key]);
}
}
returnthis;
},
base:Base
};
Base.extend=function(_instance,_static){//subclass
/**
*Base类原型的扩展别名,将这个当成一个方法调用
*/
varextend=Base.prototype.extend;
/**
*buildtheprototype,创建原型
*设置原型标志
*/
Base._prototyping=true;
/**
*创建一个Base的实例,初始化继承部分
*继承方式大致还是以下方式
*functionA(){}
*functionB(){
*this.b=[];
*}
*A.prototype=newB();//A继承B的所有属性和方法
*这种继承方式会有一个问题,B中声明的对象(如b)以prototype的形式
*被A继承之后,prototype只是生成一个指向B中对象的引用,即
*A所有实例会共同享有B中对象(b)
*vara1=newA();
*vara2=newA();
*a1.b.push("a11");
*a2.b.push("a21");
*此时,a1.b=a2.b=["a11","a21"],
*
*DeanEdwards在实现继承的时候,以父类为基础,创建实例,
*利用extend扩展该实例,最后用A.prototype=newB();实现继承
*但是属性是对象的时候没有做处理,
*还是没有避开上述的继承缺陷
*/
varproto=newthis;
/**
*在这里,不可以用proto.extend(_instance)代替
*/
extend.call(proto,_instance);
/**
*类实例属性和方法的原型部分构造完毕,删除标志位
*/
deleteBase._prototyping;
/**
*这里作者运用了适配器的模式,用自定义的构造器生成一个新的类对象
*wrapper/adapter:通过一定的方法,一个对象封装或授权另一个
*对象来改变它的接口或者行为
*/
//createthewrapperfortheconstructorfunction
/**
*获得构造器的引用
*/
varconstructor=proto.constructor;
/**
*建立klass的Function对象,调用自定义的构造器,klass就是衍生的子类
*两种情况下,调用此方法:
*1.创建类实例的时候,这时候不是原型构造阶段,执行由extend方法
*继承的时候设定的构造方法
*2.当用extend方法衍生子类的时候---newthis
*因为下文中klass的属性已经全部获得,
*所以当new完之后,获得所有父类的方法和属性都包含在了
*proto里面了,这时候,在proto的基础上运用prototype的extend方法
*将此子类的属性和方法添加到proto里面
*/
varklass=proto.constructor=function(){
/**
*varproto=newthis;调用父类的构造函数,创建一个父类的实例
*newthis用完后,函数重定向到子类对象构造方法
*/
if(!Base._prototyping){
/**
*当在构造函数中(constructor)调用base方法时,
*base方法会调用父类对象的构造函数,这时候会嵌套
*调用这个代码段,方法得以执行的条件就是this._constructing==true
*/
if(this._constructing||this.constructor==klass){//instantiation
this._constructing=true;
constructor.apply(this,arguments);
deletethis._constructing;
}
/**
*
*不再向下执行
*/
else{//casting
varobject=arguments[0];
if(object!=null){
(object.extend||extend).call(object,proto);
}
returnobject;
}
}
};
//buildtheclassinterface
/**
*
*/
for(variinBase){
klass[i]=this[i];
}
/**
*创建继承链
*/
klass.ancestor=this;
klass.base=Base.base;
klass.prototype=proto;
klass.toString=this.toString;
/**
*扩展类方法,属性,类似java的static
*/
extend.call(klass,_static);
//classinitialisation如果存在init函数调用
if(typeofklass.init=="function")
klass.init();
returnklass;
};
//initialise
Base=Base.extend({
constructor:function(){
this.extend(arguments[0]);
}
},{
ancestor:Object,
base:Base,
implement:function(_interface){
if(typeof_interface=="function"){
//ifit"safunction,callit
_interface(this.prototype);
}
else{
//addtheinterfaceusingtheextend()method
this.prototype.extend(_interface);
}
returnthis;
}
});