天天看點

extjs3.3.1中繼承實作代碼的抽取和調用

今天看了一下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》(我是還沒來得及看,有空再看)

繼續閱讀