zoukankan      html  css  js  c++  java
  • Javascript OOP框架YOOP重构实践(上) Wonder

    大家好!今天跟大家一起分享我的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,这样能反映职责。

  • 相关阅读:
    【linux 爱好者群】程序猿的那些聊天记录
    开发技巧记录
    tcmalloc 内存分析
    mktime很慢就自己去实现一个吧
    bash变量常用技巧
    文本处理sed常用操作
    【TED】如何掌握你的自由时间
    vim粘贴代码问题
    工作方式的反思-20170319
    【one day one linux】find 用法详解小记
  • 原文地址:https://www.cnblogs.com/chaogex/p/3125776.html
Copyright © 2011-2022 走看看