今天看了一下extjs中继承部分的代码,并把它抽取出来,加了些注释,并写了调用方法。具体如下:
<script>
Ext = function() { };Ext.isIE = false;//这里就不去管是不是IE了,不是问题的重点,我是在firefox下调试处理的。Ext.apply = function(o, c, defaults){ // no "this" reference for friendly out of scope calls if(defaults){ Ext.apply(o, defaults); } //extjs在这里做了子类方法对父类方法的覆盖处理 if(o && c && typeof c == 'object'){ for(var p in c){ o[p] = c[p]; } } return o;};
Ext.override=function(origclass, overrides){ if(overrides){ var p = origclass.prototype; Ext.apply(p, overrides); if(Ext.isIE && overrides.hasOwnProperty('toString')){ p.toString = overrides.toString; } } };Ext.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){ //只有两个参数的情况下,将参数转成三个参数的形式统一处理 if(typeof sp == 'object'){ overrides = sp; sp = sb; //如果只有两个参数,将第二个参数的constructor作为subclass //这也出现了另人迷惑的问题:传两个参数时,生成类实例时,sp的constructor会执行, //而传三个参数时,overrides的constructor不会执行,这也是无奈之举,javascript没有java的overload特性 //extjs的代码注释也有说明:传三个参数的形式下,第一个参数就是subclass的constructor,第二个是superclass,第三个参数用于copied into the subclass's prototype sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; } //造了一个空构造方法的函数,用来接收superclass的prototype var F = function(){}, sbp, spp = sp.prototype;
F.prototype = spp; //原型继承的关键代码在这里,将subclass的原型指向一个F的实例,用F的实例比直接用superclass的实例好, //原因在于这样处理创建子类时就不用执行superclass的构造函数,而是执行一个空构造函数F sbp = sb.prototype = new F(); //修正subclass的prototype的constructor指向 sbp.constructor=sb; //其实subclass的superclass为superclass的prototype sb.superclass=spp; //父类在创建完后,其constructor都不会是Object的constructor,为什么要修正父类的constructor,这个搞不明白 if(spp.constructor == oc){ spp.constructor=sp; } sb.override = function(o){ Ext.override(sb, o); }; sbp.superclass = sbp.supr = (function(){ return spp; }); sbp.override = io; //这里把overrides的方法拷贝给子类的prototype Ext.override(sb, overrides); //给子类添加extend方法,调用时只传overrides参数就可以生成子类的子类 sb.extend = function(o){return Ext.extend(sb, o);}; return sb; }(); //返回的是匿名方法的执行结果,也就是sb }; //第一种创建方法,传三个参数创建子类 var Person=function(name){ this.name=name;} Person =Ext.extend(Person,Object,{ getName: function(prefix) { return this.name; }});
var p=new Person("person");console.log("name:"+p.getName());
//第二种创建方法,传两个参数创建子类var Employee =Ext.extend(Person,{ constructor: function(name, employeeID) { // 调用父类的方法,这个是参照ext源码写出来的调用方法,感觉不是很爽 Employee.superclass.constructor.apply(this,[name]); this.employeeID = employeeID; console.log(employeeID); }, getEmployeeID: function() { return this.employeeID; } }); var ee=new Employee("employee",11); console.log("name:"+ee.getName()+",id:"+ee.getEmployeeID());
//第三种创建方法,调父类的extend方法创建子类var Employer =Person.extend({ constructor: function(name, employerID) { Employer.superclass.constructor.apply(this,[name]); this.employerID = employerID; console.log(employerID); }, getEmployerID: function() { return this.employerID; } });var er=new Employer("employer",12); console.log("name:"+er.getName()+",id:"+er.getEmployerID());</script>
javascript的继承实现可以参考:
1.《悟透javascript》
2.帖子: [原创]JavaScript继承详解
3.还有一本书《Object-Oriented Javascript》(我是还没来得及看,有空再看)
