Javascript OOP框架YOOP重构实践(上)

大家好!今天跟大家一起分享我的OOP框架YOOP重构实践,希望能与大家一起共同学习、共同进步。

本文展示了我对没有编写测试的YOOP原始版本的重构过程。通过该重构,力图将一个杂乱无章的遗留代码重构为有良好测试的、结构良好、可读性较强的高质量代码。

在本次重构中,我不但会对代码结构进行重构,还会改变部分行为(如将“抽象类要检查是否实现了接口成员和父类的抽象方法”修改为“抽象类不检查是否实现了接口成员和父类的抽象方法”;将“抽象类、类只能继承1个接口”修改为“可以继承多个接口”等等)。改变行为时,必须先添加或者修改测试,然后才能小步地改变行为。

原始版本

(function () {



    /************************************************** String对象扩展 ***********************************************************

    

    扩展方法:

    contain

    containIgnoreCase

    trim



    */

    if (!String.prototype.contain) {

        String.prototype.contain = function (str) {

            /* 使用RegExp对象来构造动态匹配。

            注意!str是字符串,因此需要转义!



            由于JavaScript字符串中的“\”是一个转义字符,因此,使用显式构造函数创建RegExp实例对象时,应将原始正则表达式中的“\”用“\\”替换。例如,在代码1.2中的两条语句是等价的。



            代码1.2   转义字符中的“\”:1.2.htm



            <script language="javascript">



            var re1 = new RegExp("\\d{5}");



            var re2 = /\d{5}/;



            alert("re1="+re1+"\nre2="+re2);



            </script>



         



            由于正则表达式模式文本中的转义字符也是“\”,如果正则表达式中要匹配原义字符“\”,在正则表达式模式文本中要以“\\”来表示,当使用显式构造函数的方式创建RegExp实例对象的时候,就需要使用“\\\\”来表示原义字符“\”。



            var re = new RegExp(\\\\)。



            */

            var reg = new RegExp(str);

            if (this.match(reg)) {  //用this指针指代本体

                return true;

            }

            else {

                return false;

            }

        }

    }



    /*****************************************************************************************************************************/





    //当前是否处于创建类的阶段。

    //放在自执行函数中,initializing就是自执行函数的内部变量,自执行函数的上下文结束后,外部就不能访问initializing了。

    //不用var的话,就不是当前上下文的一个变量了,而是全局对象的一个属性。这样外部就能够访问了。

    var initializing = false;

    //    var count = 0;





    //获得函数的参数数组

    function argumentNames(fn) {

        var names = fn.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1].replace(/\s+/g, '').split(',');

        return names.length == 1 && !names[0] ? [] : names;

    };



    /* 深拷贝

    */

    function extendDeep(parent, child) {

        var i,

                toStr = Object.prototype.toString,

                sArr = "[object Array]",

                sOb = "[object Object]",

                type = "",

        child = child || {};



        for (i in parent) {

            //if (parent.hasOwnProperty && parent.hasOwnProperty(i)) {



            //                if (typeof parent[i] === 'object') {    //null === 'object'也为true!



            type = toStr.call(parent[i]);

            if (type === sArr || type === sOb) {    //如果为数组或object对象

                child[i] = type === sArr ? [] : {};

                extendDeep(parent[i], child[i]);

            } else {

                child[i] = parent[i];

            }

        }

        //}

        return child;

    };





    //获得函数名

    function getFunctionName(fn) {

        var name = "";



        if (!fn) {

            return null;

        }



        name = fn.toString().match(/^.*function\s*([^\(]*)/);

        return name === null ? name : name[1];

    };



    //判断是否为数组

    function isArray(val) {

        return Object.prototype.toString.call(val) === "[object Array]";

    };



    //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的抽象方法/属性 或 接口方法/属性。

    //不用hasOwnProperty判断!否则就检查不到是否包含了父类的抽象方法/属性 或 接口方法/属性。

    function check(parentClass, interface, children) {

        //        if (!parent || !interface || !children) {

        //            throw new Error("check - arguments error!");

        //        }



        var name = "";



        if (parentClass) {

            //检查是否实现了抽象方法/属性

            for (name in parentClass.prototype) {

                if (parentClass.prototype.hasOwnProperty(name)) {

                    //                console.log(name);

                    if (name === "constructor") {

                        continue;

                    }

                    if (name.contain("Abstract_")) {

                        //抽象方法

                        if (typeof parentClass.prototype[name] === "function") {

                            if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] !== "function") {

                                //                            var t = name.slice(9);

                                throw new Error("Abstract method '" + name + "' must be overwrited!");

                            }

                        }

                            //抽象属性

                        else {

                            if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] === "function") {

                                //                            var t = name.slice(9);

                                //                            var p = children[name.slice(9)];

                                //                            var q = typeof children[name.slice(9)];

                                throw new Error("Abstract attribute '" + name + "' must be overwrited!");

                            }

                        }

                    }

                }

            }

        }



        if (!interface) {

            return;

        }



        //检查是否实现了接口方法/属性

        for (name in interface.prototype) {

            //                console.log(name);

            if (name === "constructor") {

                continue;

            }

            //                if (interface.prototype.hasOwnProperty(name)) {

            //接口方法

            if (typeof interface.prototype[name] === "function") {

                //                    var t = name.slice(10);

                //                    var m = children[name.slice(10)];

                //                        console.log("t = " + t);

                //                        console.log("m = " + m);

                if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] !== "function") {

                    throw new Error("Interface method '" + name + "' must be overwrited!");

                }

            }

                //接口属性

            else {

                //                    var t = name.slice(10);

                //                    var m = children[name.slice(10)];

                //                        console.log("t = " + t);

                //                        console.log("m = " + m);

                if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] === "function") {

                    throw new Error("Interface attribute '" + name + "' must be overwrited!");

                }

            }

            //                }

        }

    };



    //检查抽象成员

    function addAbstract(abstract, currentClass, temp) {

        var name = "";



        for (name in abstract) {

            if (abstract.hasOwnProperty(name)) {

                //                if (typeof abstract[name] !== "function") {

                //                    throw new Error("Virtual attribute is not allowed!");

                //                }

                //                else {

                //抽象方法前面加"Abstract_"前缀

                currentClass.prototype["Abstract_" + name] = abstract[name];

                //                currentClass.prototype[name] = abstract[name];



                temp[name] = abstract[name];    //加入temp

                //                }

            }

        }

    };



    //检查虚方法(不能为虚属性)

    function addVirtual(virtual, currentClass, temp) {

        var name = "";



        for (name in virtual) {

            if (virtual.hasOwnProperty(name)) {

                if (typeof virtual[name] !== "function") {

                    throw new Error("Virtual attribute is not allowed!");

                }

                else {

                    currentClass.prototype[name] = virtual[name];



                    temp[name] = virtual[name];    //加入temp

                }

            }

        }

    };



    //加入密封方法。

    //没有实现检查子类是否重写了父类的密封方法,只是定义了一个规范。

    function addSealed(sealed, currentClass, temp) {

        var name = "";



        for (name in sealed) {

            if (sealed.hasOwnProperty(name)) {

                currentClass.prototype[name] = sealed[name];



                temp[name] = sealed[name];    //加入temp

            }

        }

    };



    //获得在原型prototype中不存在同名的str。

    //如果有同名,则加上前缀"_"

    function getNoRepeatStrInPrototype(prototype, str) {

        var new_str = "";



        if (!prototype[str]) {

            return str;

        }



        new_str = "_" + str;

        return getNoRepeatStrInPrototype(prototype, new_str);

    }









    //创建接口

    //接口可以继承接口

    function MyInterface(_parent, _method, _attribute) {

        var i = 0, args = null;



        var parent = null,

            method = null,

            attribute = null;



        if (typeof _parent === "function") {

            if (getFunctionName(_parent) !== "I") {

                throw new Error("Interface must inherit interface!");

            }

            else {

                parent = _parent;



                //形如“MyInterface(Parent, "A", "B", "GetName");”

                if (_method && !isArray(_method)) {

                    method = Array.prototype.slice.call(arguments, 1);

                    attribute = null;

                }

                    //形如“MyInterface(Parent, ["A", "B", "GetName"], ["a", "c"]);”

                else {

                    method = _method;

                    attribute = _attribute;

                }

            }

            //            console.log(parent.toString());

        }

        else {

            parent = null;

            //形如“MyInterface("A", "B", "GetName");”

            if (_method && !isArray(_method)) {

                method = arguments

                attribute = null;

            }

                //形如“MyInterface(["A", "B", "GetName"], ["a", "c"]);”

            else {

                method = arguments[0];

                attribute = arguments[1];

            }

        }



        function I() {

        }



        // 如果此接口需要从其它接口扩展

        if (parent) {

            I.prototype = new parent();

            I.prototype.constructor = I;

        }



        //        console.log("method = " + method);

        //        console.log("attribute = " + attribute);





        //        //形如“MyInterface(["A", "B", "GetName"], ["a", "c"]);”

        //        if (isArray(method)) {



        //方法

        for (i = 0; i < method.length; i++) {

            //加上前缀“Interface_”

            I.prototype["Interface_" + method[i]] = function () {

                throw new Error("This method must be overwrited!");

            };

        }

        //属性

        if (attribute) {

            if (!isArray(attribute)) {

                throw new Error("Attribute must be array!");

            }

            else {

                for (i = 0; i < attribute.length; i++) {

                    //加上前缀“Interface_”

                    I.prototype["Interface_" + attribute[i]] = 0;

                }

            }

        }

        //        }

        //        //形如“MyInterface("A", "B", "GetName");”

        //        else {

        //            args = Array.prototype.slice.call(arguments, 1);

        //            //方法

        //            for (i = 0; i < args.length; i++) {

        //                I.prototype[args[i]] = function () {

        //                    throw new Error("This method must be overwrited!");

        //                };

        //            }

        //        }



        return I;

    };







    //创建抽象类

    //抽象类能够继承接口、抽象类以及实体类,但此处约定抽象类只能继承接口和抽象类,不能继承实体类!

    //(这样方便判断抽象类是否包含全部的父类(接口/抽象类)成员)

    function MyAbstract(_parent, _prop) {

        var Static = null;

        var k = null, name = null, temp = {},

            virtual = {};



        //        if (arguments.length > 1) {

        //            throw new Error("AbstractClass can't inherit other classes!");

        //        }



        var abstractClass = null,

                interface = null,

            prop = null;



        //原型恢复标志,用于防止第一次创建实例时恢复原型

        var mark_resume = false;





        //取出父类、接口

        if (arguments.length === 1) {

            prop = arguments[0];

            //            parent = null;

            abstractClass = null;

            interface = null;

        }

            //_parent为{Class: xx, Interface: xx}

        else if (typeof _parent === "object") {



            if (!_parent.Class && !_parent.Interface) {

                throw new Error("Please add AbstractClass or Interface!");

            }

            if (getFunctionName(_parent.Class) === "F" || getFunctionName(_parent.Interface) === "F") {

                throw new Error("AbstractClass here can't inherit parentClass which is created by MyClass function!");

            }



            abstractClass = _parent.Class;

            interface = _parent.Interface;



            prop = _prop;

        }

            //_parent直接为xx,就表示父类为抽象类

        else if (typeof _parent === "function") {

            if (getFunctionName(_parent) === "F") {

                throw new Error("AbstractClass here can't inherit parentClass which is created by MyClass function!");

            }



            abstractClass = _parent;

            interface = null;



            prop = _prop;

        }

        else {

            throw new Error("arguments is not allowed!");

        }





        Static = prop.Static ? prop.Static : null;





        // 本次调用所创建的类(构造函数)

        function A() {

            //            // 如果抽象父类存在,则实例对象的baseClass指向父类的原型

            //            // 这就提供了在实例对象中调用父类方法的途径

            //            if (abstractClass) {

            //                this.baseClass = abstractClass.prototype;

            //            }



            ////防止第一次创建实例时恢复原型

            //if (mark_resume) {

            //    //还原原型

            //    extendDeep(A.prototype.backUp_prototype, A.prototype);

            //}

            //else {

            //    mark_resume = true;

            //}



        }



        // 如果此接口需要从其它接口扩展

        if (abstractClass) {

            //            //删除父类的私有成员,保留本类的私有成员

            //            for (name in abstractClass.prototype) {

            //                if (abstractClass.prototype.hasOwnProperty(name)) {

            //                    //私有成员以“_”开头,可能有多个“_”(多层继承)

            //                    if (!name.match(/^_+/)) {

            //                        //                                                delete parentClass.prototype[name];

            //                        A.prototype[name] = abstractClass.prototype[name];

            //                    }

            //                }

            //            }



            //A.prototype = new abstractClass();

            A.prototype = extendDeep(abstractClass.prototype);



            A.prototype.constructor = A;



            // 如果父类存在,则实例对象的baseClass指向父类的原型。

            // 这就提供了在实例对象中调用父类方法的途径。

            //baseClass的方法是指向abstractClass的,不是指向F(子类)的!



            A.prototype[getNoRepeatStrInPrototype(abstractClass.prototype, "baseClass")] = abstractClass.prototype;

            //A.prototype.baseClass = abstractClass.prototype;

        }



        //加入构造函数

        //抽象类本身因为不能实例化,所以不调用构造函数。

        //抽象类中的构造函数供子类构造函数中调用。

        if (prop.Init) {

            if (abstractClass) {

                A.prototype.Init = function (name) {

                    return function () {

                        //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

                        this.base = function () {

                            //这个写法也可以!为什么不用apply修正this也行??!

                            //parentClass.prototype[name](); 



                            //此处的arguments为base方法传入的形参

                            //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

                            return abstractClass.prototype[name].apply(abstractClass.prototype, arguments);

                        };

                        //指向子类,可以用于模版模式

                        this.baseToSubClass = abstractClass.prototype[name];



                        //执行fn并返回执行的结果

                        //此处的arguments为F.prototype[name]方法传入的形参。

                        return prop[name].apply(this, arguments);

                    };



                }("Init");

            }

            else {

                A.prototype.Init = prop.Init;

            }

        }



        if (prop.Private) {

            //私有属性/方法直接覆盖

            for (name in prop.Private) {

                if (prop.Private.hasOwnProperty(name)) {

                    A.prototype[name] = prop.Private[name];

                }

            }

        }



        if (prop.Public) {

            for (name in prop.Public) {

                if (prop.Public.hasOwnProperty(name)) {

                    //检查抽象成员,抽象成员放到Public或Protected中

                    if (name === "Abstract") {

                        addAbstract(prop["Public"][name], A, temp);

                        continue;

                    }

                    //检查虚方法,虚方法放到Public或Protected中

                    if (name === "Virtual") {

                        addVirtual(prop["Public"][name], A, temp);

                        continue;

                    }

                    //密封的方法(不允许子类重写)

                    if (name === "Sealed") {

                        addSealed(prop["Public"][name], A, temp);

                        continue;

                    }



                    if (abstractClass &&

            typeof prop.Public[name] === "function" &&

            typeof A.prototype[name] === "function") {

                        A.prototype[name] = function (name) {

                            return function () {

                                //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

                                this.base = function () {

                                    //这个写法也可以!为什么不用apply修正this也行??!

                                    //parentClass.prototype[name](); 



                                    //此处的arguments为base方法传入的形参

                                    //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

                                    return abstractClass.prototype[name].apply(abstractClass.prototype, arguments);

                                };

                                //指向子类,可以用于模版模式

                                this.baseToSubClass = abstractClass.prototype[name];



                                //执行fn并返回执行的结果

                                //此处的arguments为F.prototype[name]方法传入的形参。

                                return prop.Public[name].apply(this, arguments);

                            };



                        }(name);

                    }

                    else {

                        A.prototype[name] = prop.Public[name];

                    }







                    temp[name] = prop.Public[name];    //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性

                }

            }

        }

        //保护成员

        if (prop.Protected) {

            for (name in prop.Protected) {

                if (prop.Protected.hasOwnProperty(name)) {

                    //检查抽象成员,抽象成员放到Public或Protected中

                    if (name === "Abstract") {

                        addAbstract(prop["Protected"][name], A, temp);

                        continue;

                    }

                    //检查虚方法,虚方法放到Public或Protected中

                    if (name === "Virtual") {

                        addVirtual(prop["Protected"][name], A, temp);

                        continue;

                    }

                    //密封的方法(不允许子类重写)

                    if (name === "Sealed") {

                        addSealed(prop["Protected"][name], A, temp);

                        continue;

                    }

                    A.prototype[name] = prop.Protected[name];



                }

            }

        }











        //        //虚方法(不能为虚属性)

        //        if (prop.Virtual) {

        //            for (name in prop.Virtual) {

        //                if (prop.Virtual.hasOwnProperty(name)) {

        //                    if (typeof prop.Virtual[name] !== "function") {

        //                        throw new Error("Virtual attribute is not allowed!");

        //                    }

        //                    else {

        //                        //                        //虚方法前面加"Virtual_"前缀,在子类中要检查虚方法

        //                        A.prototype[name] = prop.Virtual[name];



        //                        temp[name] = prop.Virtual[name];    //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性

        //                    }

        //                }

        //            }

        //        }





        //抽象类可以没有抽象成员

        //        if (!prop.Abstract) {

        //            throw new Error("AbstractClass must have abstract methods!");

        //        }



        //放到外面的抽象成员,默认为公有抽象成员

        for (name in prop.Abstract) {

            if (prop.Abstract.hasOwnProperty(name)) {

                //                console.log();

                //抽象方法前面加"Abstract_"前缀

                A.prototype["Abstract_" + name] = prop.Abstract[name];



                temp[name] = prop.Abstract[name];   //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性

            }

        }



        //        //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的抽象方法/属性 或 接口方法/属性

        //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的接口方法/属性

        check(null, interface, temp);



        //静态属性/方法赋值

        for (k in Static) {

            A[k] = Static[k];

        }



        ////备份原型

        //A.prototype.backUp_prototype = extendDeep(A.prototype);



        return A;

    }







    //    //是否调用父类函数

    //    var base_flag = false;



    //创建普通类

    //父类_parent可以为{Class: xx, Interface: xx},或者直接为xx类

    function MyClass(_parent, _prop) {

        //        console.log("length = " + arguments.length);

        var Static = null;

        //                    Private = null,

        //            Public = null,

        //            Origin = null;



        var k = null, name = null;



        var parentClass = null, interface = null, prop = null, temp = {};

        //        var temp = null;



        //        //原型备份容器,用于创建实例时,恢复最初的原型(每次创建实例时,原型都保持不变)。

        //        var backUp_prototype = {};



        //原型恢复标志,用于防止第一次创建实例时恢复原型

        var mark_resume = false;





        //取出父类、接口

        if (arguments.length === 1) {

            prop = arguments[0];

            parentClass = null;

            interface = null;

        }

            //{Class: xx, Interface: xx}

        else if (typeof _parent === "object") {

            //            if (parent.Class)

            if (!_parent.Class && !_parent.Interface) {

                throw new Error("Please add Class or Interface!");

            }



            parentClass = _parent.Class;

            interface = _parent.Interface;



            prop = _prop;

        }

            //直接为xx类

        else if (typeof _parent === "function") {

            parentClass = _parent;

            interface = null;

            //            parent = _parent;

            //            interface = null;



            prop = _prop;

        }

        else {

            throw new Error("arguments is not allowed!");

        }







        //取出静态属性/方法、私有属性/方法、公有属性/方法

        //        Private = prop.Private;



        //        Public = prop.Public;



        Static = prop.Static ? prop.Static : null;







        //        //保存原始的私有属性,用于创建实例时,重置私有属性

        //        //        var Origin = {};

        //        //        Origin = Private

        //        Origin = operate.extendDeep(Private);

        //        YYC.Tool.extend.extend(Origin, Private);





        //        //访问公共属性/方法的入口,

        //        MyClass.Public = Public;





        // 本次调用所创建的类(构造函数)

        function F() {

            //            console.log(mark_resume);







            //防止第一次创建实例时恢复原型

            if (mark_resume) {

                //var t = F.prototype.backUp_prototype;

                //var m = F.prototype;



                //还原原型

                //extendDeep(F.prototype.backUp_prototype, F.prototype);

                extendDeep(F.backUp_prototype, F.prototype);





                //F.prototype.backUp_prototype = extendDeep(F.prototype);

            }

            else {

                mark_resume = true;

            }



            // 如果当前处于实例化类的阶段,则调用Init原型函数

            if (!initializing) {

                //                console.log("F");

                //                // 如果父类存在,则实例对象的baseClass指向父类的原型

                //                // 这就提供了在实例对象中调用父类方法的途径

                //                if (parentClass) {

                //                    this.baseClass = parentClass.prototype;

                //                    //                    console.log(this.baseClass);

                //                }

                this.Init && this.Init.apply(this, arguments);

            }



            //            this.Public = Public;



            //            console.log("F");





            //            if (this.)

            //            console.log(this._m);

            //            delete this._m;



            //            delete F.prototype._m;

            //            delete F.prototype._a;

            //            this._m = null;

            //            this._a = null;

            //            delete F.prototype._a;







            /*不能删除私有成员和保护成员!否则类的成员就不能调用到私有和保护的成员了(因为已经删除了)!

            对象的创建算法参考http://www.cnblogs.com/TomXu/archive/2012/02/06/2330609.html









            //删除私有成员和保护成员,这样外界就不能访问私有和保护成员了!

            for (name in this) {

            if (name.search(/(^_)|(^P_)/) !== -1) {

            delete F.prototype[name];

            //                                                    this[name] = null;

            }

              

            }

            */







            //            console.log(count);

            //            count++;



            //不使用MyClass.self!因为该属性为静态属性,如果创建了该类后,又创建了类A,则MyClass.self会指向类A!



            //            MyClass的静态属性self指向创建的类的实例,可以通过self来访问实例的属性和方法

            //            MyClass.self = this;











            //            Private.C();



            //            for (name in Private) {

            //                Private[name].call(this);

            //            }









        }









        //        Private.C = Private.C.call(null, Public);



        //        Private.call(F, null);



        //                Private.M = (function (pub) {

        //                    return function () {

        //                        Private.M.call(null, arguments);

        //                    }

        //                }(Public));





        //        for (name in Private) {

        //            Private[name] = function () {

        //                //            console.log("1111111");

        //                return function () {

        //                    //                console.log("222222222");

        //                    return Private[name].call(this, arguments);

        //                }



        //            };

        //        }







        //        Private.C = function () {

        //            return function () {

        //                Private.C.call(F, arguments);

        //            }

        //        };





        // 如果此类需要从其它类扩展

        if (parentClass) {



            initializing = true;

            //F.prototype = new parentClass();

            F.prototype = extendDeep(parentClass.prototype);





            F.prototype.constructor = F;



            //            for (name in parentClass.prototype) {

            //                if (parentClass.prototype.hasOwnProperty(name)) {

            //                    //私有成员不继承

            //                    if (!name.match(/^_/)) {

            //                        F.prototype[name] = parentClass.prototype[name];

            //                    }

            //                }

            //            }



            //            //删除父类的私有成员,保留本类的私有成员

            //            for (name in parentClass.prototype) {

            //                if (parentClass.prototype.hasOwnProperty(name)) {

            //                    //私有成员以“_”开头,可能有多个“_”(多层继承)

            //                    if (!name.match(/^_+/)) {

            //                        //                                                delete parentClass.prototype[name];

            //                        F.prototype[name] = parentClass.prototype[name];

            //                    }

            //                }

            //            }



            //            console.log(F.prototype.constructor);





            // 如果父类存在,则实例对象的baseClass指向父类的原型。

            // 这就提供了在实例对象中调用父类方法的途径。

            //baseClass的方法是指向parentClass的,不是指向F(子类)的!

            //F.prototype.baseClass = parentClass.prototype;





            F.prototype[getNoRepeatStrInPrototype(parentClass.prototype, "baseClass")] = parentClass.prototype;



            initializing = false;

        }



        if (prop.Init) {







            // 如果此类继承自父类parent并且父类原型中存在同名函数name

            if (parentClass &&

    typeof prop.Init === "function" &&

    typeof F.prototype.Init === "function") {

                F.prototype.Init = function (name) {

                    return function () {

                        this.base = function () {

                            return parentClass.prototype[name].apply(parentClass.prototype, arguments);

                        };

                        //指向子类,可以用于模版模式

                        this.baseToSubClass = parentClass.prototype[name];

                        //执行fn并返回执行的结果

                        //此处的arguments为F.prototype[name]方法传入的形参。

                        return prop[name].apply(this, arguments);

                    };



                }("Init");

            }

            else {

                F.prototype.Init = prop.Init;

            }

        }





        //        Private.call(this);



        //        if (parentClass && parentClass.prototype["JudgeDoubleHit"]) {

        //            console.log(parentClass.toString());





        if (parentClass) {

            for (name in parentClass.prototype) {

                if (parentClass.prototype.hasOwnProperty(name)) {

                    //如果不是抽象方法/保护方法/私有方法/接口成员,则加入到temp中。

                    //用于添加父类的密封方法(因为子类并没有加入父类的密封方法)。

                    if (!name.match(/^Abstract_/) || !name.match(/^P_/) || !name.match(/^_/) || !name.match(/^Interface_/)) {

                        temp[name] = parentClass.prototype[name];

                    }

                }

            }

        }











        //        }



        //        if (this.baseClass.Protected) {

        //            if (this.baseClass.Protected.Sealed) {



        //                for (k in this.baseClass.Protected.Sealed) {

        //                    temp[k] = this.baseClass.Protected.Sealed[k];

        //                }

        //            }

        //        }





        if (prop.Private) {

            //私有属性/方法直接覆盖

            for (name in prop.Private) {

                if (prop.Private.hasOwnProperty(name)) {

                    F.prototype[name] = prop.Private[name];

                }

            }

        }



        //        if (!prop.Public) {

        //            throw new Error("Class must have public methods!");

        //        }

        //        else {



        //        }





        //保护成员

        if (prop.Protected) {

            for (name in prop.Protected) {

                if (prop.Protected.hasOwnProperty(name)) {

                    //检查虚方法,虚方法放到Public或Protected中

                    if (name === "Virtual") {

                        addVirtual(prop["Protected"][name], F, temp);

                        continue;

                    }

                    //密封的方法(不允许子类重写)

                    if (name === "Sealed") {

                        addSealed(prop["Protected"][name], F, temp);

                        continue;

                    }



                    F.prototype[name] = prop.Protected[name];



                    //如果父类有保护抽象成员,此处检查子类的保护成员是否实现了父类的保护抽象成员

                    temp[name] = prop.Protected[name];

                }

            }

        }



        //        //虚方法(不能为虚属性)

        //        if (prop.Virtual) {

        //            for (name in prop.Virtual) {

        //                if (prop.Virtual.hasOwnProperty(name)) {

        //                    if (typeof prop.Virtual[name] !== "function") {

        //                        throw new Error("Virtual attribute is not allowed!");

        //                    }

        //                    else {

        //                        F.prototype[name] = prop.Virtual[name];



        //                        temp[name] = prop.Virtual[name];    //加入temp

        //                    }

        //                }

        //            }

        //        }



        if (prop.Abstract) {

            throw new Error("Only abstractClass can have abstract methods!");

        }







        if (prop.Public) {

            // 覆盖父类的同名公有方法

            for (name in prop.Public) {

                //            console.log("for in name = " + name);

                //            //私有属性/方法不加入到原型中

                //            if (name === "Private") {

                ////                console.log("continue");

                //                continue;

                //            }



                if (prop.Public.hasOwnProperty(name)) {

                    //检查虚方法,虚方法放到Public或Protected中

                    if (name === "Virtual") {

                        addVirtual(prop["Public"][name], F, temp);

                        continue;

                    }

                    //密封的方法(不允许子类重写)

                    if (name === "Sealed") {

                        addSealed(prop["Public"][name], F, temp);

                        continue;

                    }

                    //                    console.log("Public");

                    //                    console.log("name = " + name);

                    //                    console.log("prop.Public[name] = " + prop.Public[name]);

                    temp[name] = prop.Public[name];     //加入temp



                    // 如果此类继承自父类parent并且父类原型中存在同名函数name

                    if (parentClass &&

            typeof prop.Public[name] === "function" &&

            typeof F.prototype[name] === "function") {

                        //                        console.log("parent!");









                        F.prototype[name] = function (name) {

                            return function () {

                                /*此处如果写成“this.base = parentClass.prototype[name];”,则在使用this.base()调用父类同名方法时,

                                父类同名方法的this指针是指向F的!(即指向子类,而不是指向父类!)   为什么????

                                如:

                                var Person = MyAbstract({

                                Init: function (name) {

                                this.name = name;

                                },

                                Public: {

                                m: 1,

                                getEmployeeID: function () {

                                console.log(this.m);

                                }

                                }

                                }

                                });





                                var Employee = MyClass({

                                Init: function (name) {

                                this.name = name;

                                },

                                Public: {

                                m: 100,

                                getEmployeeID: function () {

                                this.baseClass.getEmployeeID();

                                this.base();

                                }

                                }

                                });



                                var m = new Employee();

                                m.getEmployeeID();    //输出:1  100



                                分析:

                            

                                this.baseClass.getEmployeeID()的this指向Person,而this.base()的this指向Employee!



                                解决方案:



                                用apply修正this.base()中的this,使其指向父类。

                                */





                                //                                if (!this.base) {

                                //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

                                this.base = function () {

                                    //这个写法也可以!为什么不用apply修正this也行??!

                                    //parentClass.prototype[name](); 



                                    //此处的arguments为base方法传入的形参

                                    //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

                                    return parentClass.prototype[name].apply(parentClass.prototype, arguments);



                                    //                                    this.baseClass.

                                };

                                //                                }

                                //                                if (!this.baseToSubClass) {

                                //指向子类,可以用于模版模式

                                this.baseToSubClass = parentClass.prototype[name];

                                //                                }



                                //                                this.base = function () {

                                //                                    //                                    console.log(base_flag);



                                //                                    Private = {

                                //                                    };

                                ////                                    base_flag = true;

                                //                                    return parent.prototype[name];

                                //                                };

                                //                            console.log("arg = " + arg);



                                //执行fn并返回执行的结果

                                //此处的arguments为F.prototype[name]方法传入的形参。

                                return prop.Public[name].apply(this, arguments);

                            };



                        }(name);



                    }

                    else {

                        //                    console.log();

                        //公有属性

                        if (typeof (prop.Public[name]) !== "function") {

                            F.prototype[name] = prop.Public[name];

                        }

                            //公有方法

                        else {

                            /* 如果不传入Public[name],而直接在自执行函数中调用Public[name],如

                            F.prototype[name] = function () {

                            return function () {

                            prop.Public[name].apply(this, arguments);

                            };

                            } ();



                            或者写成:

                            F.prototype[name] = function () {

                            prop.Public[name].call(this, arguments);

                            };

                        

                        

                            这样的话,在创建实例时调用方法时,都会执行MyClass中的最后一个函数!见下例

                        

                            var Person = MyClass({

                            Init: function (name) {

                            this.name = name;

                            },

                            getName: function () {

                            console.log("getName");

                            },

                            getEmployeeID: function ($private) {

                            console.log("Person getEmployeeID");

                            }

                            });

                            var m = new Person("name");     

                            m.getName();    //第一种和第二种写法此处会输出:"Person getEmployeeID"

                



                            这样执行的原因是:



                            (引用自“深入理解JavaScript系列(16):闭包(Closures)”)

                            同一个父上下文中创建的闭包是共用一个[[Scope]]属性的。也就是说,

                            某个闭包对其中[[Scope]]的变量做修改会影响到其他闭包对其变量的读取。

                            这就是说:所有的内部函数都共享同一个父作用域。



                            也就是说,function里面的name都是共用父作用域中的name!所以此处F.prototype[name]被激活的时候,

                            name都为最后一个值即"getEmployeeID"。

                            所以F原型上的方法都指向"getEmployeeID"



                            解决方案:



                            创建一个闭包来保存name的值。

                            */

                            F.prototype[name] = function (name) {

                                return function () {

                                    return prop.Public[name].apply(this, arguments);     //执行fn并返回执行的结果

                                };

                            }(name);



                        }

                    }

                }

            }

        }









        //检查公有成员和虚函数是否实现了抽象方法/属性 或 接口方法/属性

        check(parentClass, interface, temp);





        //静态属性/方法赋值

        for (k in Static) {

            F[k] = Static[k];

        }







        //备份原型

        //F.prototype.backUp_prototype = extendDeep(F.prototype);

        F.backUp_prototype = extendDeep(F.prototype);





        return F;

    };



    YYC.Pattern.namespace("Frame").MyInterface = MyInterface;



    YYC.Pattern.namespace("Frame").MyAbstract = MyAbstract;



    YYC.Pattern.namespace("Frame").MyClass = MyClass;

}());
View Code

代码分析

我并不打算对代码详细说明,因为该文的重点在于展示重构的过程。因此我介绍下原始版本实现OOP的核心内容,具体请参考代码。

MyInterface为接口,MyAbstract为抽象类,MyClass为类。

创建一个接口,可以这样写:

var A = YYC.Frame.MyInterface("method1", "method2");

调用“YYC.Frame.MyInterface”时,会调用MyInterface函数,该函数会把参数解析,把方法和属性加上前缀“Interface_”,加入到内部函数I.prototype中,然后返回内部函数I。

因此,A就具有了接口方法和接口属性,但是我们不会直接使用接口(如创建A的实例,访问接口方法),因为接口的方法和属性(统称为成员)并没有实现,需要在继承接口的类中实现。

然后创建一个抽象类:

var B = YYC.Frame.MyAbstract({

    Protected: {    //保护成员

        Abstract: { //保护抽象成员

        },

        Virtual: {  //保护虚方法

        },

        P_proA: true,   //保护属性

        P_proM: function () { }    //保护方法

    },

    Public: {   //公有成员

        Abstract: { //公有抽象成员

        },

        Virtual: {  //公有虚方法

        },

        pubM: function () { },  //公有方法

        pubA: 0    //公有属性

    },

    Private: {  //私有成员

        _priA: "",   //私有属性

        _priM: function () { } //私有方法

    },

    Abstract: { //公有抽象成员

    },

    Virtual: {  //公有虚方法

    }

});
View Code

调用“YYC.Frame.MyAbstract”时,会调用MyAbstract函数,该函数会把参数解析,将公有成员、私有成员、保护成员都加入到内部函数A.prototype中(约定私有成员、保护成员的命名规则,约定使用框架者遵守访问权限)。

抽象成员(Abstract:{}中的成员)先加上前缀“Abstract_”,然后加入到A.prototype中(子类根据前缀来区分判断是否实现了父类的抽象成员)。

然后创建一个类,继承接口A和抽象类B:

var C = YYC.Frame.MyClass({Interface: A, Class: B},{

    Init: function () { //构造函数

    },

    Protected: {    //保护成员

    },

    Public: {   

        Virtual: { 

        },

        method1: function () { }, 

        method2: function () { }

    },

    Private: {  //私有成员

        _priA: "",   //私有属性

        _priM: function () { } //私有方法

    }

});
View Code

调用“YYC.Frame.MyClass”时,会调用MyClass函数,该函数会把参数解析,将公有成员、私有成员、保护成员都加入到内部函数F.prototype中。

构造函数Init在F的构造函数function F(){}中调用,从而在创建C的实例时,会调用构造函数Init。

此处继承了接口A和抽象类B,因此会先用深拷贝的方法来将A、B的成员加入到F.prototype中,然后判断是否实现A的接口成员(根据“Interface_”前缀来判断)、是否实现B的抽象成员(根据“Abstract_”前缀来判断),如果没有实现会抛出异常。

为什么要用深拷贝来实现继承

//F.prototype = new parentClass();

F.prototype = extendDeep(parentClass.prototype);

此处继承使用深拷贝来实现,原因是为了解决下面的问题:

  • 若父类Parent的属性为引用类型(数组或对象)a,有两个子类Sub1、Sub2。如果子类Sub1的实例s1对a进行修改或者sub调用修改a的方法,则子类Sub2的实例的a为修改过后的a!

问题描述

var Parent = YYC.Frame.MyClass({

    Private:{

        _a: []

    },

    Public: {

        add: function () {

            this._a.push("a");

        }

    }

});

var Sub1 = YYC.Frame.MyClass(Parent, {});

var Sub2 = YYC.Frame.MyClass(Parent, {});



var t = new Sub1();

t.add();

console.log(t.a);        //["a"]

var k = new Sub2();

console.log(k.a);    //照理说应该为[],但实际上却是["a"]!

原因分析

上例中的“t.add();”修改的是实例t的_a属性,实例t的_a属性与Parent.prototype._a指向同一个数组。因此修改实例t的_a就相当于修改了Parent.prototype._a。

解决方案

修改类继承方式,改为通过深拷贝的方式拷贝父类原型的成员来实现继承:

F.prototype = extendDeep(parentClass.prototype);

这样实例t的_a属性和Parent.protype._a就指向不同的数组了。

为什么要重构

原始版本对其它的库有依赖(如依赖于namespace.js),有太多没用或错误的注释,混在一起的职责,过于庞大的函数,函数名、属性名不能很好地体现职责,多层嵌套的条件式等等。另外,最大的问题是没有对应的测试套件。

开始重构

编写测试

回到本次重构中来,要进行重构,首先需要坚固的测试作保证。我使用Jasmine作为Javascript的测试工具。建议大家先可以看下javascript单元测试,里面介绍了单元测试的工具,包括Jasmine。

先编写几个主要的测试,测试是否解决了我之前发现的几个问题。

describe("oopFrame", function () {

    describe("测试Class", function () {

        describe("获得公有成员", function () {

            it("如果父类不存在,能够正确获得公有方法", function () {

                var Class = YYC.Frame.MyClass({

                    Public: {

                        a: function () {

                            this.b = 1;

                            return 0;

                        }

                    }

                });



                var cla = new Class();

                var result = cla.a();



                expect(result).toEqual(0);

                expect(cla.b).toEqual(1);

            });

        });

    });



    describe("集成测试", function () {

        it("测试解决“若父类的属性为引用类型(数组或对象)a,则如果子类的实例s1对a进行修改或者sub调用修改a的方法,则第二次创建实例s2的a为修改过后的a!”的问题", function () {

            var Parent = YYC.Frame.MyAbstract({

                Init: function () {

                    console.log("Parent Init!");

                },

                Public: {

                    a: [],

                }

            });

            var Sub = YYC.Frame.MyClass(Parent, {

                Init: function () {

                },

                Public: {

                }

            });



            var t = new Sub();

            t.a.push("a");

            var m = new Sub();



            expect(m.a).toEqual([]);

        });

        it("测试解决“若父类Parent的属性为引用类型(数组或对象)a,有两个子类Sub1、Sub2。如果子类Sub1的实例s1对a进行修改或者sub调用修改a的方法,则子类Sub2的实例的a为修改过后的a!”的问题", function () {

            var Parent = YYC.Frame.MyAbstract({

                Init: function () {

                    console.log("Parent Init!");

                },

                Public: {

                    a: [],

                    add: function () {

                        this.a.push("a");

                    }

                }

            });

            var Sub1 = YYC.Frame.MyClass(Parent, {

                Init: function () {

                },

                Public: {

                }

            });

            var Sub2 = YYC.Frame.MyClass(Parent, {

                Init: function () {

                }

            });



            var t = new Sub1();

            t.a.push("a");

            var k = new Sub2();



            expect(k.a).toEqual([]);



        });

        it("测试解决“若A1为抽象类,A2(抽象类)继承于A1,B(类)继承于A2,A1、A2、B都有同名方法a,A2和B在a方法中都通过this.baseClass调用父类同名方法。则如果B的实例b调用a方法,则A2、B的a方法中的this.baseClass均指向A2(照理说A2的this.baseClass应该指向A1)!”的问题", function () {

            var A1 = YYC.Frame.MyAbstract({

                Public: {

                    arr: [],

                    a: function () {

                        this.arr.push(1);

                    }

                }

            });

            var A2 = YYC.Frame.MyAbstract(A1, {

                Public: {

                    a: function () {

                        this.arr.push(2);

                        this.baseClass.a.call(this, null);

                    }

                }

            });

            var B = YYC.Frame.MyClass(A2, {

                Public: {

                    a: function () {

                        this.arr.push(3);

                        this._baseClass.a.call(this, null);



                        return this.arr;

                    }

                }

            });

            var b = new B();



            expect(b.a()).toEqual([3, 2, 1]);

        });

    });

});
View Code

现在测试的覆盖面还不全,有些代码没有测试到。不过我们已经构建了主要的测试,剩下的测试可以在后续的重构中逐渐加入。

测试页面

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<!DOCTYPE HTML>

<html>

<head id="Head1" runat="server">

   <title>Jasmine Spec Runner</title>

  <link rel="stylesheet" type="text/css" href="<%=Url.Content("~/Scripts/jasmine/lib/jasmine-1.3.1/jasmine.css") %>" />

        <script src="<%=Url.Content("~/Scripts/jasmine/lib/jasmine-1.3.1/jasmine.js") %>"></script>

    <script src="<%=Url.Content("~/Scripts/jasmine/lib/jasmine-1.3.1/jasmine-html.js") %>"></script>

  <!-- include source files here... -->

    <script src="<%=Url.Content("~/Scripts/jquery-1.7.js")%>"></script>

    <script src="../../Scripts/myTool/pattern/createObject/namespace.js"></script>

    <script src="<%=Url.Content("~/Scripts/myTool/frame/YOOP.js")%>"></script>

  <!-- include spec files here... -->

    <script src="<%=Url.Content("~/Scripts/jasmine/spec/helper/specHelper.js")%>"></script>

    <script src="../../Scripts/jasmine/spec/frameSpec/YOOPSpec.js"></script>

</head>

<body>





  <script type="text/javascript">

      (function () {

              var jasmineEnv = jasmine.getEnv();

              jasmineEnv.updateInterval = 1000;



              var htmlReporter = new jasmine.HtmlReporter();



              jasmineEnv.addReporter(htmlReporter);



              jasmineEnv.specFilter = function (spec) {

                  return htmlReporter.specFilter(spec);

              };

              function execJasmine() {

                  jasmineEnv.execute();

              }





              var currentWindowOnload = window.onload;







              if (currentWindowOnload) {

                  currentWindowOnload();

              }

              execJasmine();

      })();

</script>



</body>

</html>
View Code

在测试页面中运行测试,通过全部测试。

解除对其它库的依赖

现在该框架通过了测试,能够正常工作。但是因为它采用命名空间模式,需要依赖于namespace.js库。

我想解除这个依赖,因此直接在框架中定义YYC命名空间,并且考虑到该框架的通用性较高,因此将其命名空间YYC.Frame更改为YYC。

修改框架为:

window.YYC = window.YYC || {};

...

YYC.MyInterface = MyInterface;

YYC.MyAbstract = MyAbstract;

YYC.MyClass = MyClass;

测试页面中去掉对namespace.js的引用。

修改类名 

类名MyInterface、MyAbstract、MyClass太长了,而且个人气息太浓,因此将类名改为Interface、AClass、Class。

重构this.base,this.baseToSubClass

原始版本:

A.prototype[name] = function (name) {

    return function () {

        //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

        this.base = function () {

            //这个写法也可以!为什么不用apply修正this也行??!

            //parentClass.prototype[name](); 



            //此处的arguments为base方法传入的形参

            //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

            return abstractClass.prototype[name].apply(abstractClass.prototype, arguments);

        };

        //指向子类,可以用于模版模式

        this.baseToSubClass = abstractClass.prototype[name];



        //执行fn并返回执行的结果

        //此处的arguments为F.prototype[name]方法传入的形参。

        return prop.Public[name].apply(this, arguments);

    };



}(name);

原版中,子类使用this.base调用父类同名函数(函数中this指向父类同名函数),子类使用this.baseToSubClass调用父类同名函数(函数中this指向子类同名函数)。

考虑到一般都是使用this.baseToSubClass,因此将this.base改名为this.baseToParent,this.baseToSubClass改名为this.base,并不再使用this.baseToParent。

重构版本:

return function () {

    /*

    //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

    this.baseToParrent = function () {

        //这个写法也可以!为什么不用apply修正this也行??!

        //parentClass.prototype[name](); 



        //此处的arguments为baseToParrent方法传入的形参

        //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

        return parentClass.prototype[name].apply(parentClass.prototype, arguments);

    };

    */

    //指向子类,可以用于模版模式

    this.base = parentClass.prototype[name];



    //执行fn并返回执行的结果

    //此处的arguments为F.prototype[name]方法传入的形参。

    return prop[name].apply(this, arguments);

};

重构结构

分析代码结构,发现AClass与Class联系的比较紧密,而Interface则可以单独为一块,因此对代码进行分块:

(function(){    //A结构

    (function(){    //A1结构

        function Interface(){

        };



        YYC.Interface = Interface;

    }());



    (function(){    //A2结构

        function AClass(){

        };



        function Class(){

        };



        YYC.AClass = AClass;

        YYC.Class = Class;

    }());

}());

提取工具函数

在工具函数的名字中加入前缀“_”,表示为私有函数。

将Interface、AClass、Class共用的工具函数提出来,放到A中。然后将AClass、Class共用的工具函数提出来放到A2中:

(function(){    //A结构

    window.YYC = window.YYC || {};



    /************************************************** String对象扩展 ***********************************************************

    

    扩展方法:

    contain

    containIgnoreCase

    trim



    */

    if (!String.prototype.contain) {

        String.prototype.contain = function (str) {

            var reg = new RegExp(str);

            if (this.match(reg)) {  //用this指针指代本体

                return true;

            }

            else {

                return false;

            }

        }

    }



    /*****************************************************************************************************************************/





    ////获得函数的参数数组

    //function argumentNames(fn) {

    //    var names = fn.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1].replace(/\s+/g, '').split(',');

    //    return names.length == 1 && !names[0] ? [] : names;

    //};





    //获得函数名

    function _getFunctionName(fn) {

        var name = "";



        if (!fn) {

            return null;

        }



        name = fn.toString().match(/^.*function\s*([^\(]*)/);

        return name === null ? name : name[1];

    };



    //判断是否为数组

    function _isArray(val) {

        return Object.prototype.toString.call(val) === "[object Array]";

    };



    (function(){    //A1结构

        function Interface(){

        };

    }());



    (function(){    //A2结构

        /* 深拷贝

*/

        function _extendDeep(parent, child) {

            var i = null,

            len = 0,

                  toStr = Object.prototype.toString,

                  sArr = "[object Array]",

                  sOb = "[object Object]",

                  type = "",

           _child = null;



            //数组的话,不获得Array原型上的成员。

            if (toStr.call(parent) === sArr) {

                _child = child || [];



                for (i = 0, len = parent.length; i < len; i++) {

                    type = toStr.call(parent[i]);

                    if (type === sArr || type === sOb) {    //如果为数组或object对象

                        _child[i] = type === sArr ? [] : {};

                        _extendDeep(parent[i], _child[i]);

                    } else {

                        _child[i] = parent[i];

                    }

                }

            }

                //对象的话,要获得原型链上的成员。因为考虑以下情景:

                //类A继承于类B,现在想要拷贝类A的实例a的成员(包括从类B继承来的成员),那么就需要获得原型链上的成员。

            else if (toStr.call(parent) === sOb) {

                _child = child || {};



                for (i in parent) {

                    //if (parent.hasOwnProperty && parent.hasOwnProperty(i)) {



                    //                if (typeof parent[i] === 'object') {    //null === 'object'也为true!



                    type = toStr.call(parent[i]);

                    if (type === sArr || type === sOb) {    //如果为数组或object对象

                        _child[i] = type === sArr ? [] : {};

                        _extendDeep(parent[i], _child[i]);

                    } else {

                        _child[i] = parent[i];

                    }

                }

                //}

            }

            else {

                _child = parent;

            }





            return _child;

        };

        //获得在原型prototype中不存在同名的str。

        //如果有同名,则加上前缀"_"

        function _getNoRepeatStrInPrototype(prototype, str) {

            var new_str = "";



            if (!prototype[str]) {

                return str;

            }

            new_str = "_" + str;



            return _getNoRepeatStrInPrototype(prototype, new_str);

        }



        function AClass(){

        };



        function Class(){

        };



        YYC.AClass = AClass;

        YYC.Class = Class;

    }());

}());
View Code

重构_check函数

注意到_check函数太大,因此需要根据职责来提取出小函数。

_check有两个职责:

  1. 检查是否实现了父类的抽象方法/属性。
  2. 检查是否实现了接口方法/属性。

重构前:

function _check(parentClass, interface, children) {

    var name = "";



    if (parentClass) {

        //检查是否实现了抽象方法/属性

        for (name in parentClass.prototype) {

            if (parentClass.prototype.hasOwnProperty(name)) {

                if (name === "constructor") {

                    continue;

                }

                if (name.contain("Abstract_")) {

                    //抽象方法

                    if (typeof parentClass.prototype[name] === "function") {

                        if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] !== "function") {

                            throw new Error("Abstract method '" + name + "' must be overwrited!");

                        }

                    }

                        //抽象属性

                    else {

                        if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] === "function") {

                            throw new Error("Abstract attribute '" + name + "' must be overwrited!");

                        }

                    }

                }

            }

        }

    }

    if (!interface) {

        return;

    }

    //检查是否实现了接口方法/属性

    for (name in interface.prototype) {

        if (name === "constructor") {

            continue;

        }

        //接口方法

        if (typeof interface.prototype[name] === "function") {

            if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] !== "function") {

                throw new Error("Interface method '" + name + "' must be overwrited!");

            }

        }

            //接口属性

        else {

            if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] === "function") {

                throw new Error("Interface attribute '" + name + "' must be overwrited!");

            }

        }

    }

};
View Code

重构后:

//检查子类的公有方法+虚方法+抽象方法是否包含父类的抽象方法/属性 或 接口方法/属性。

//不用hasOwnProperty判断!否则就检查不到是否包含了父类的抽象方法/属性 或 接口方法/属性。

function _check(parentClass, interface, children) {

    if (parentClass) {

        _checkAbstract(parentClass, children);

    }

    else if (interface) {

        _checkInterface(interface, children);

    }

};

function _checkAbstract(parentClass, children) {

    var name = "";



    for (name in parentClass.prototype) {

        if (parentClass.prototype.hasOwnProperty(name)) {

            if (name === "constructor") {

                continue;

            }

            if (name.contain("Abstract_")) {

                //抽象方法

                if (typeof parentClass.prototype[name] === "function") {

                    if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] !== "function") {

                        throw new Error("Abstract method '" + name + "' must be overwrited!");

                    }

                }

                    //抽象属性

                else {

                    if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] === "function") {

                        throw new Error("Abstract attribute '" + name + "' must be overwrited!");

                    }

                }

            }

        }

    }

};

function _checkInterface(interface, children) {

    var name = "";



    for (name in interface.prototype) {

        if (name === "constructor") {

            continue;

        }

        //接口方法

        if (typeof interface.prototype[name] === "function") {

            if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] !== "function") {

                throw new Error("Interface method '" + name + "' must be overwrited!");

            }

        }

            //接口属性

        else {

            if (children[name.slice(10)] === undefined || typeof children[name.slice(10)] === "function") {

                throw new Error("Interface attribute '" + name + "' must be overwrited!");

            }

        }



    }

};
View Code

_checkAbstract、_checkInterface中的“if (children[name.slice(9)] === undefined || typeof children[name.slice(9)] !== "function") {”等条件语句很难理解,因此将其封装成函数:

function _checkAbstract(parentClass, children) {

    var name = "";



    for (name in parentClass.prototype) {

        if (parentClass.prototype.hasOwnProperty(name)) {

            if (name === "constructor") {

                continue;

            }

            if (name.contain("Abstract_")) {

                //抽象方法

                if (typeof parentClass.prototype[name] === "function") {

                    if (_noMethodForAbstract(children, name) && _noMethodForAbstract(parentClass.prototype, name)) {

                        throw new Error("Abstract method '" + name + "' must be overwrited!");

                    }

                }

                    //抽象属性

                else {

                    if (_noAttritubeForAbstract(children, name) && _noAttritubeForAbstract(parentClass.prototype, name)) {

                        throw new Error("Abstract attribute '" + name + "' must be overwrited!");

                    }

                }

            }

        }

    }

};

function _checkInterface(interface, children) {

    var name = "";



    for (name in interface.prototype) {

        if (name === "constructor") {

            continue;

        }

        //接口方法

        if (typeof interface.prototype[name] === "function") {

            if (_noMethodForInterface(children, name) && _noMethodForInterface(parentClass.prototype, name)) {

                throw new Error("Interface method '" + name + "' must be overwrited!");

            }

        }

            //接口属性

        else {

            if (_noAttritubeForInterface(children, name) && _noAttritubeForInterface(parentClass.prototype, name)) {

                throw new Error("Interface attribute '" + name + "' must be overwrited!");

            }

        }

    }

};

function _noMethodForAbstract(_class, name) {

    return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] !== "function";

};

function _noAttritubeForAbstract(_class, name) {

    return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] === "function";

};

function _noMethodForInterface(_class, name) {

    return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] !== "function";

};

function _noAttritubeForInterface(_class, name) {

    return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] === "function";

};
View Code

重构Interface

现在让我们看下function Interface(){}中的代码:

//创建接口

//接口可以继承接口

function Interface(_parent, _method, _attribute) {

    var i = 0, args = null;



    var parent = null,

        method = null,

        attribute = null;



    if (typeof _parent === "function") {

        if (_getFunctionName(_parent) !== "I") {

            throw new Error("Interface must inherit interface!");

        }

        else {

            parent = _parent;



            //形如“MyInterface(Parent, "A", "B", "GetName");”

            if (_method && !_isArray(_method)) {

                method = Array.prototype.slice.call(arguments, 1);

                attribute = null;

            }

                //形如“MyInterface(Parent, ["A", "B", "GetName"], ["a", "c"]);”

            else {

                method = _method;

                attribute = _attribute;

            }

        }

        //            console.log(parent.toString());

    }

    else {

        parent = null;

        //形如“MyInterface("A", "B", "GetName");”

        if (_method && !_isArray(_method)) {

            method = arguments

            attribute = null;

        }

            //形如“MyInterface(["A", "B", "GetName"], ["a", "c"]);”

        else {

            method = arguments[0];

            attribute = arguments[1];

        }

    }



    function I() {

    }



    // 如果此接口需要从其它接口扩展

    if (parent) {

        I.prototype = new parent();

        I.prototype.constructor = I;

    }



    //        console.log("method = " + method);

    //        console.log("attribute = " + attribute);





    //        //形如“MyInterface(["A", "B", "GetName"], ["a", "c"]);”

    //        if (isArray(method)) {



    //方法

    for (i = 0; i < method.length; i++) {

        //加上前缀“Interface_”

        I.prototype["Interface_" + method[i]] = function () {

            throw new Error("This method must be overwrited!");

        };

    }

    //属性

    if (attribute) {

        if (!isArray(attribute)) {

            throw new Error("Attribute must be array!");

        }

        else {

            for (i = 0; i < attribute.length; i++) {

                //加上前缀“Interface_”

                I.prototype["Interface_" + attribute[i]] = 0;

            }

        }

    }

    //        }

    //        //形如“MyInterface("A", "B", "GetName");”

    //        else {

    //            args = Array.prototype.slice.call(arguments, 1);

    //            //方法

    //            for (i = 0; i < args.length; i++) {

    //                I.prototype[args[i]] = function () {

    //                    throw new Error("This method must be overwrited!");

    //                };

    //            }

    //        }



    return I;

};
View Code

该函数包含了太多的职责,应该把每一个职责提取为一个内部函数,然后再在Interface中调用这些内部函数:

//创建接口

//接口可以继承接口

function Interface(_parent, _method, _attribute) {

    var i = 0, args = null;

    var parent = null,

        method = null,

        attribute = null;



    function _getByParent() {

        if (typeof _parent === "function") {

            if (_getFunctionName(_parent) !== "I") {

                throw new Error("Interface must inherit interface!");

            }

            else {

                parent = _parent;

                //形如“Interface(Parent, "A", "B", "GetName");”

                if (_method && !_isArray(_method)) {

                    method = Array.prototype.slice.call(arguments, 1);

                    attribute = null;

                }

                    //形如“Interface(Parent, ["A", "B", "GetName"], ["a", "c"]);”

                else {

                    method = _method;

                    attribute = _attribute;

                }

            }

        }

        else {

            parent = null;

            //形如“Interface("A", "B", "GetName");”

            if (_method && !_isArray(_method)) {

                method = arguments

                attribute = null;

            }

                //形如“Interface(["A", "B", "GetName"], ["a", "c"]);”

            else {

                method = arguments[0];

                attribute = arguments[1];

            }

        }

    };

    function _inherit() {

        I.prototype = new parent();

        I.prototype.constructor = I;

    };

    function _addMethod() {

        for (i = 0; i < method.length; i++) {

            //加上前缀“Interface_”

            I.prototype["Interface_" + method[i]] = function () {

                throw new Error("This method must be overwrited!");

            };

        }

    };

    function _addAttribute() {

        if (attribute) {

            if (!_isArray(attribute)) {

                throw new Error("Attribute must be array!");

            }

            else {

                for (i = 0; i < attribute.length; i++) {

                    //加上前缀“Interface_”

                    I.prototype["Interface_" + attribute[i]] = 0;

                }

            }

        }

    };



    function I() {

    }



    _getByParent();

    // 如果此接口需要从其它接口扩展

    if (parent) {

        _inherit();

    }

    //方法

    _addMethod();

    //属性

    _addAttribute();



    return I;

};
View Code

重构AClass、Class

AClass、Class中有一些重复的代码,将这些重复的代码提取为函数,放到结构A2中,供AClass、Class调用:

(function(){    //A2结构

    //检查抽象成员

    function _addAbstract(abstract, currentClass, temp) {

        var name = "";



        for (name in abstract) {

            if (abstract.hasOwnProperty(name)) {

                //抽象方法前面加"Abstract_"前缀

                currentClass.prototype["Abstract_" + name] = abstract[name];

                temp[name] = abstract[name];    //加入temp

            }

        }

    };

    //检查虚方法(不能为虚属性)

    function _addVirtual(virtual, currentClass, temp) {

        var name = "";



        for (name in virtual) {

            if (virtual.hasOwnProperty(name)) {

                if (typeof virtual[name] !== "function") {

                    throw new Error("Virtual attribute is not allowed!");

                }

                else {

                    currentClass.prototype[name] = virtual[name];

                    temp[name] = virtual[name];    //加入temp

                }

            }

        }

    };

    //加入密封方法。

    //没有实现检查子类是否重写了父类的密封方法,只是定义了一个规范。

    function _addSealed(sealed, currentClass, temp) {

        var name = "";



        for (name in sealed) {

            if (sealed.hasOwnProperty(name)) {

                currentClass.prototype[name] = sealed[name];

                temp[name] = sealed[name];    //加入temp

            }

        }

    };

    function _addStatic(_class, prop) {

        var Static = null;

        var k = null;



        Static = prop.Static ? prop.Static : null;

        //静态属性/方法赋值

        for (k in Static) {

            _class[k] = Static[k];

        }

    };

    function _inherit(_class, parentClass) {

        _class.prototype = _extendDeep(parentClass.prototype);

        _class.prototype.constructor = _class;



        // 如果父类存在,则实例对象的baseClass指向父类的原型。

        // 这就提供了在实例对象中调用父类方法的途径。

        //baseClass的方法是指向parentClass的,不是指向F(子类)的!

        _class.prototype[_getNoRepeatStrInPrototype(parentClass.prototype, "baseClass")] = parentClass.prototype;

    };

    function _addInit(_class, parentClass, prop) {

        if (prop.Init) {

            // 如果此类继承自父类parent并且父类原型中存在同名函数name

            if (parentClass &&

    typeof prop.Init === "function" &&

    typeof _class.prototype.Init === "function") {

                //if (parentClass) {

                _class.prototype.Init = function (name) {

                    return function () {

                        /*

                        //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

                        this.baseToParrent = function () {

                            //这个写法也可以!为什么不用apply修正this也行??!

                            //parentClass.prototype[name](); 

    

                            //此处的arguments为baseToParrent方法传入的形参

                            //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

                            return parentClass.prototype[name].apply(parentClass.prototype, arguments);

                        };

                        */

                        //指向子类,可以用于模版模式

                        this.base = parentClass.prototype[name];



                        //执行fn并返回执行的结果

                        //此处的arguments为F.prototype[name]方法传入的形参。

                        return prop[name].apply(this, arguments);

                    };



                }("Init");

            }

            else {

                _class.prototype.Init = prop.Init;

            }

        }

    };

    function _addPrivate(_class, private) {

        if (private) {

            //私有属性/方法直接覆盖

            for (name in private) {

                if (private.hasOwnProperty(name)) {

                    _class.prototype[name] = private[name];

                }

            }

        }

    };

    //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的抽象方法/属性 或 接口方法/属性。

    //不用hasOwnProperty判断!否则就检查不到是否包含了父类的抽象方法/属性 或 接口方法/属性。

    function _check(parentClass, interface, children) {

        if (parentClass) {

            _checkAbstract(parentClass, children);

        }

        else if (interface) {

            _checkInterface(interface, children);

        }

    };

    function _checkAbstract(parentClass, children) {

        var name = "";



        for (name in parentClass.prototype) {

            if (parentClass.prototype.hasOwnProperty(name)) {

                if (name === "constructor") {

                    continue;

                }

                if (name.contain("Abstract_")) {

                    //抽象方法

                    if (typeof parentClass.prototype[name] === "function") {

                        if (_noMethodForAbstract(children, name) && _noMethodForAbstract(parentClass.prototype, name)) {

                            throw new Error("Abstract method '" + name + "' must be overwrited!");

                        }

                    }

                        //抽象属性

                    else {

                        if (_noAttritubeForAbstract(children, name) && _noAttritubeForAbstract(parentClass.prototype, name)) {

                            throw new Error("Abstract attribute '" + name + "' must be overwrited!");

                        }

                    }

                }

            }

        }

    };

    function _checkInterface(interface, children) {

        var name = "";



        for (name in interface.prototype) {

            if (name === "constructor") {

                continue;

            }

            //接口方法

            if (typeof interface.prototype[name] === "function") {

                if (_noMethodForInterface(children, name) && _noMethodForInterface(parentClass.prototype, name)) {

                    throw new Error("Interface method '" + name + "' must be overwrited!");

                }

            }

                //接口属性

            else {

                if (_noAttritubeForInterface(children, name) && _noAttritubeForInterface(parentClass.prototype, name)) {

                    throw new Error("Interface attribute '" + name + "' must be overwrited!");

                }

            }

        }

    };

    function _noMethodForAbstract(_class, name) {

        return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] !== "function";

    };

    function _noAttritubeForAbstract(_class, name) {

        return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] === "function";

    };

    function _noMethodForInterface(_class, name) {

        return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] !== "function";

    };

    function _noAttritubeForInterface(_class, name) {

        return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] === "function";

    };



    function AClass(){

    };



    function Class(){

    };



    YYC.AClass = AClass;

    YYC.Class = Class;

}());
View Code

将AClass中的每一个职责提取为一个内部函数,然后再在AClass中调用这些内部函数:

//创建抽象类

//抽象类能够继承接口、抽象类以及实体类,但此处约定抽象类只能继承接口和抽象类,不能继承实体类!

//(这样方便判断抽象类是否包含全部的父类(接口/抽象类)成员)



function AClass(_parent, _prop) {



    var name = null, temp = {};

    var parentClass = null,

            interface = null,

        prop = null;



    ////原型恢复标志,用于防止第一次创建实例时恢复原型

    //var mark_resume = false;



    function _getByParent() {

        //if (arguments.length === 1) {

        if (_prop === undefined) {

            prop = _parent;

            parentClass = null;

            interface = null;

        }

        else if (typeof _parent === "object") {



            if (!_parent.Class && !_parent.Interface) {

                throw new Error("Please add AbstractClass or Interface!");

            }

            if (_getFunctionName(_parent.Class) === "F" || _getFunctionName(_parent.Interface) === "F") {

                throw new Error("AbstractClass here can't inherit parentClass which is created by Class function!");

            }



            parentClass = _parent.Class;

            interface = _parent.Interface;



            prop = _prop;

        }

            //_parent直接为xx,就表示父类为抽象类

        else if (typeof _parent === "function") {

            if (_getFunctionName(_parent) === "F") {

                throw new Error("AbstractClass here can't inherit parentClass which is created by Class function!");

            }



            parentClass = _parent;

            interface = null;



            prop = _prop;

        }

        else {

            throw new Error("arguments is not allowed!");

        }

    };

    function _prepareAndAddPublic() {

        if (prop.Public) {

            for (name in prop.Public) {

                if (prop.Public.hasOwnProperty(name)) {

                    if (_prepareCheck("Public") === "continue") {

                        continue;

                    }

                    _addPublic();

                }

            }

        }

    };

    function _addPublic() {

        if (parentClass &&

            typeof prop.Public[name] === "function" &&

            typeof A.prototype[name] === "function") {

            A.prototype[name] = function (name) {

                return function () {

                    /*

                    //此处不用创建闭包了!因为外面已经创建了闭包,name已经被保存了!

                    this.baseToParrent = function () {

                        //这个写法也可以!为什么不用apply修正this也行??!

                        //parentClass.prototype[name](); 



                        //此处的arguments为baseToParrent方法传入的形参

                        //注意!要加上“return”,这样才能返回parentClass.prototype[name]的返回值

                        return parentClass.prototype[name].apply(parentClass.prototype, arguments);

                    };

                    */

                    //指向子类,可以用于模版模式

                    this.base = parentClass.prototype[name];



                    //执行fn并返回执行的结果

                    //此处的arguments为F.prototype[name]方法传入的形参。

                    return prop.Public[name].apply(this, arguments);

                };



            }(name);

        }

        else {

            A.prototype[name] = prop.Public[name];

        }

    }

    function _prepareAndAddProtected() {

        if (prop.Protected) {

            for (name in prop.Protected) {

                if (prop.Protected.hasOwnProperty(name)) {

                    if (_prepareCheck("Protected") === "continue") {

                        continue;

                    }

                    A.prototype[name] = prop.Protected[name];



                }

            }

        }

    };

    function _prepareCheck(where) {

        //检查抽象成员,抽象成员放到Public或Protected中

        if (name === "Abstract") {

            _addAbstract(prop[where][name], A, temp);

            return "continue";

        }

        //检查虚方法,虚方法放到Public或Protected中

        if (name === "Virtual") {

            _addVirtual(prop[where][name], A, temp);

            return "continue";

        }

        //密封的方法(不允许子类重写)

        if (name === "Sealed") {

            _addSealed(prop[where][name], A, temp);

            return "continue";

        }



        temp[name] = prop[where][name];    //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性

        return null;

    };



    // 本次调用所创建的类(构造函数)

    function A() {

    }





    //取出父类、接口

    _getByParent();



    // 如果此接口需要从其它接口扩展

    if (parentClass) {

        _inherit(A, parentClass);

    }



    //加入构造函数

    //抽象类本身因为不能实例化,所以不调用构造函数。

    //抽象类中的构造函数供子类构造函数中调用。

    _addInit(A, parentClass, prop);



    _addPrivate(A, prop.Private);



    _prepareAndAddPublic();





    //保护成员

    _prepareAndAddProtected();



    //放到外面的抽象成员,默认为公有抽象成员

    _addAbstract(prop.Abstract, A, temp);



    _addStatic(A, prop);



    //检查抽象类的公有方法+虚方法+抽象方法是否包含父类的接口方法/属性

    _check(null, interface, temp);



    return A;

};
View Code

同理Class重构为:

//创建普通类

//父类_parent可以为{Class: xx, Interface: xx},或者直接为xx类



function Class(_parent, _prop) {

    //当前是否处于创建类的阶段。

    var initializing = false;

    var name = null;

    var parentClass = null, interface = null, prop = null, temp = {};

    //原型恢复标志,用于防止第一次创建实例时恢复原型

    var mark_resume = false;



    function _getByParent() {

        if (_prop === undefined) {

            prop = _parent;

            parentClass = null;

            interface = null;

        }

            //{Class: xx, Interface: xx}

        else if (typeof _parent === "object") {

            if (!_parent.Class && !_parent.Interface) {

                throw new Error("Please add Class or Interface!");

            }



            parentClass = _parent.Class;

            interface = _parent.Interface;

            prop = _prop;

        }

            //直接为xx类

        else if (typeof _parent === "function") {

            parentClass = _parent;

            interface = null;

            prop = _prop;

        }

        else {

            throw new Error("arguments is not allowed!");

        }

    };

    function _addParentSealed() {

        for (name in parentClass.prototype) {

            if (parentClass.prototype.hasOwnProperty(name)) {

                //如果不是抽象方法/保护方法/私有方法/接口成员,则加入到temp中。

                //用于添加父类的密封方法(因为子类并没有加入父类的密封方法)。

                if (!name.match(/^Abstract_/) || !name.match(/^P_/) || !name.match(/^_/) || !name.match(/^Interface_/)) {

                    temp[name] = parentClass.prototype[name];

                }

            }

        }

    };

    function _prepareAndAddPublic() {

        if (prop.Public) {

            for (name in prop.Public) {

                if (prop.Public.hasOwnProperty(name)) {

                    if (_prepareCheck("Public") === "continue") {

                        continue;

                    }

                    _addPublic();

                }

            }

        }

    };

    function _addPublic() {

        // 如果此类继承自父类parent并且父类原型中存在同名函数name

        if (parentClass &&

typeof prop.Public[name] === "function" &&

typeof F.prototype[name] === "function") {

            F.prototype[name] = function (name) {

                return function () {

                    //指向子类,可以用于模版模式

                    this.base = parentClass.prototype[name];

                    //执行fn并返回执行的结果

                    //此处的arguments为F.prototype[name]方法传入的形参。

                    return prop.Public[name].apply(this, arguments);

                };

            }(name);



        }

        else {

            F.prototype[name] = prop.Public[name];

        }

    }

    function _prepareAndAddProtected() {

        if (prop.Protected) {

            for (name in prop.Protected) {

                if (prop.Protected.hasOwnProperty(name)) {

                    if (_prepareCheck("Protected") === "continue") {

                        continue;

                    }

                    F.prototype[name] = prop.Protected[name];



                }

            }

        }

    };

    function _prepareCheck(where) {

        //检查虚方法,虚方法放到Public或Protected中

        if (name === "Virtual") {

            _addVirtual(prop[where][name], A, temp);

            return "continue";

        }

        //密封的方法(不允许子类重写)

        if (name === "Sealed") {

            _addSealed(prop[where][name], A, temp);

            return "continue";

        }



        temp[name] = prop[where][name];    //用于检查是否包含父类的抽象方法/属性 或 接口方法/属性

        return null;

    };



    _getByParent();



    // 本次调用所创建的类(构造函数)

    function F() {

        //防止第一次创建实例时恢复原型

        if (mark_resume) {

            //还原原型

            _extendDeep(F.backUp_prototype, F.prototype);

        }

        else {

            mark_resume = true;

        }



        // 如果当前处于实例化类的阶段,则调用Init原型函数

        if (!initializing) {

            this.Init && this.Init.apply(this, arguments);

        }

        /*不能删除私有成员和保护成员!否则类的成员就不能调用到私有和保护的成员了(因为已经删除了)!

        对象的创建算法参考http://www.cnblogs.com/TomXu/archive/2012/02/06/2330609.html









        //删除私有成员和保护成员,这样外界就不能访问私有和保护成员了!

        for (name in this) {

        if (name.search(/(^_)|(^P_)/) !== -1) {

        delete F.prototype[name];

        //                                                    this[name] = null;

        }

          

        }

        */

    }



    // 如果此类需要从其它类扩展

    if (parentClass) {

        initializing = true;

        _inherit(F, parentClass);

        initializing = false;

    }



    _addInit(F, parentClass, prop);



    if (parentClass) {

        _addParentSealed();

    }



    _addPrivate(F, prop.Private);



    //保护成员

    _prepareAndAddProtected();



    if (prop.Abstract) {

        throw new Error("Only abstractClass can have abstract methods!");

    }



    _prepareAndAddPublic();



    //检查公有成员和虚函数是否实现了抽象方法/属性 或 接口方法/属性

    _check(parentClass, interface, temp);



    _addStatic(F, prop);





    //备份原型

    F.backUp_prototype = _extendDeep(F.prototype);



    return F;

};
View Code

重命名temp

AClass和Class中的局部属性temp的职责是存储该类成员的名称,从而用于检查该类成员是否实现了接口或者父类的抽象成员。

因此,将temp改名为children,这样能反映职责。

你可能感兴趣的:(JavaScript)