JS模擬類繼承

    //最後一個參數是JSON表示的類定義瀏覽器

    //若是參數大於一,則第一個參數是基類,不然,基類是object閉包

    //中間的參數是類實現的接口app

    //返回值是類,類是一個構造函數,並繼承了基類的prototype函數


    

function Class(){this

        aDefine = arguments[arguments.length - 1]; //傳入的最後一個參數是要定義的類prototype

        if(!aDefine) return; //若是沒用傳參數,則直接結束。code

        var aBase = arguments.length>1?arguments[0]:object; //若是傳的參數大於1,則第一個參數爲基類,若等於1,則基類默認爲object對象

        function prototype_(){}; //建立prototype臨時函數,用以掛接原型鏈繼承

        prototype_.prototype = aBase.prototype;接口

        var aPrototype = new prototype_(); //創建類要使用的原型對象

        for(var member in aDefine){

            if(aDefine[member] != 'Create'){ //構造函數不用掛在原型鏈上,構造函數是最終返回的

                aPrototype[member] = aDefine[member];

            }

        }

        //設置類

        if(aDefine.Create){  //若是有構造函數

            var aType = aDefine.Create; //類即爲該構造函數

        }else{ //若是沒有構造函數

            var aType = function(){ //建立默認的構造函數

                this.base.apply(this, arguments); //調用父類的構造函數

            }

        }

        aType.prototype = aPrototype;  //設置類(構造函數)的原型

        aType.Base = aBase; //設置類型關係

        aType.prototype.Type = aType; //爲本類對象擴展一個Type屬性,用以判斷對象的類型

        return aType; //將加了原型繼承的構造函數返回,就能夠new了

    }

    function object(){}; //定義object根類,用以實現最基礎的方法和屬性

    object.prototype.isA = function(type){ //判斷對象屬性是否屬於某種類型

        var self = this.Type;


        while(self){

            if(self == type){

                return true;

            }

            self = self.Base;

        }

        return false;

    }

    object.prototype.base = function(){   //調用基類的構造函數

        var Caller = object.prototype.base.caller; //獲得調用該函數的函數

        Caller && Caller.Base && Caller.Base.apply(this, arguments);

        //若是Caller存在而且 Caller.Base存在,則調用 Caller.Base方法

        //若果若是Caller或Caller.Base有一個不存在,那麼後面的語句不用再執行。

    }

    var people = Class({ //定義people類

        Create: function(name, age){

            this.base();

            this.name = name;

            this.age = age;

        },

        say: function(){

            console.log('My name is ' + this.name + ",I'm " + this.age + '.');

        }

    })

    var chinaPeople = Class(people,

        {

            Create: function(name, age, country){

                this.base(name, age);

                this.country = country;

            },

            sayCountry: function(){

                console.log('My country is ' + this.country);

            }

        }

    )

    var man1 = new people('kaka', 32);

    var man2 = new chinaPeople('kaka', 32, 'china');

    man2.say();  //My name is kaka,I'm 32.

    man2.sayCountry();  //My country is china 




caller不支持opera瀏覽器,因此重寫base方法

  object.prototype.base = function(){

        var Base = this.Type.Base; //獲取當前對象的基類

        if(!Base.Base){ //若是已經沒有基類

            Base.apply(this, arguments); //直接調用基類構造函數

        }else{

            this.base = MakeBase(Base); //先複寫this.base

            Base.apply(this, arguments);

            delete this.base; //刪除複寫的base屬性

        };

        function MakeBase(Type){

            var Base = Type.Base;

            if(!Type.Base) return Base //基類已無基類,就無需包裝

            return function(){ //包裝爲引用臨時變量Base的閉包函數

                this.base = MakeBase(Base); //先複寫this.base

                Base.apply(this, arguments); //在調用基類構造函數

            }

        }

    }

相關文章
相關標籤/搜索