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;
}
});
/*
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;
}
});
相关文章
- Fabric.js 使用图片遮盖画布(前景图)
- js/es6判断对象是否为空,并判断对象是否包含某个属性
- js 字符串截取(包含中英文)
- html js 全局 变量,JS定义全局变量
- 死磕JS:Reflect.ownKeys() 和 Object.keys() 怎么选?
- 初识js中的闭包_Js闭包中变量理解
- JS设计模式之适配器模式
- js中四舍五入的方法_JS取整
- 高频js笔试题看这一篇就够了
- 这些js原型及原型链面试题你能做对几道_2023-02-27
- 一款用GO语言编写的JS爬取工具~
- js 数组去除重复数据-当WPS开始像支持VBA一样支持JS语言时,微软又该何去何从?
- 【JS 逆向百例】猿人学系列 web 比赛第二题:js 混淆 - 动态 cookie,详细剖析
- 3. 「vue@2.6.11 源码分析」vue.js 首次执行做了哪些事情
- 如何使用jscythe并通过Node.js的Inspector机制执行任意JS代码
- js中什么是对象,对象的概念是什么详解编程语言
- JS动态引入js、CSS动态创建script/link/style标签详解编程语言
- nodejs使用Node.js优雅地整合MongoDB(mongodb整合)
- JS的递增/递减运算符和带操作的赋值运算符的等价式
- js停止输出代码
- 高效的表格行背景隔行变色及选定高亮的JS代码
- 远离JS灾难css灾难之js私有函数和css选择器作为容器
- 关于文本框默认值的操作js代码
- javascript表单验证-Parsley.js使用和配置
- 纯JS实现五子棋游戏兼容各浏览器(附源码)
- js获取本机的外网/广域网ip地址完整源码
- css样式标签和js语法属性区别
- js替代copy(示例代码)
- js正则表达式学习笔记之匹配字符串