文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>javascript面向对象基础 -- 类的创建、继承和扩展:小改prototype的class.create...

javascript面向对象基础 -- 类的创建、继承和扩展:小改prototype的class.create...

时间:2010-08-18  来源:0xff

因项目需要,重新捡起放下两年多的js,再看看Prototype、jQuery,感觉比以前好多了,至少代码看起来越来越顺眼~

不过动起手来还是感觉有不少碍眼的地方。。。

为了效率(既然大家都这么说。。)不得不放弃臃肿的Prototype,而改用VS集成的jQuery,但上手就感到很不适。。

没办法,jQuery里没有很好的面向对象继承机制,只好从Prototype把Class.create方法移植过来。

Class.create有了之后却发现对$super看的很不顺眼(不用Java的结果),于是就顺手把Class.create再改改,就成了这样子。

基类方法的调用都可以通过 this.base.方法名(参数) 原封不动的实现,这下看起来顺眼多了。。

    

下面是说明和完整代码:


     (由prototype的Class.create方法上修改)
     
     使用方法:
     定义一个新类:Class.create({类的原型方法列表}, {原型方法列表1}...);
     从已有类继承:Class.create({父类}, {子类新增或重写的原型方法列表}, {原型方法列表1}...);
    
     必要函数说明:
     定义一个全新的类时,必须实现 initialize 方法
    
     继承说明:
     继承后,子类的同名方法将覆盖父类方法,如果需要使用父类方法,可以在子类方法中可以通过 “this.base.父类的方法名称({参数})” 来调用
     注意,如果在类定义时创建属性,则所有 基类/子类 的对象都会继承这些属性的引用副本。
     例如:var A = Class.create({ P1: 0, P2: [] }); var obj1 = new A(); var obj2 = new A();
     obj1.P1++;           // 此时 obj1.P1 == 1, obj2.P1 == 0
     obj1.P2.push('a');   // 此时 obj1.P1 == obj2.P1 == ['a']
     obj1.P2 = ['b'];     // 此时 obj1.P1 == ['b'], obj2.P1 == ['a']
    
     关于基类方法交叉调用的层次问题:
     在某个基类方法递归链中,如果其中某一级方法调用了其他的基类方法,则此处调用的基类方法为调用方法同级的基类方法。
     (即子类继承不会破坏父类原有的基类方法调用链)
     如:(以下所示为 类ClassE 的 Method1 从上往下 调用基类的 Method1 方法过程)
     ClassE.Method1           ClassE.Method2
     ClassD.Method1           ClassD.Method2
     ClassC.Method1  ==> this.base.Method2() 调用,此处 Method2 的调用则从当前级别的基类(ClassB)开始。
     ClassB.Method1           ClassB.Method2
     ClassA.Method1           ClassA.Method2
     BaseClass.Method1        BaseClass.Method2
     

     (不推荐在基类方法里出现交叉调用,因为当子类调用基类方法时,基类方法中调用的其他方法可能已被重写,并调用了当前方法,导致出现死循环)

     

     
     使用示例:


     var ClassA = $.fn.Class.create({ initialize: function () { this.name = 'name:ClassA'; return this; }, showMe: function () { alert('ClassA'); return this; }, showName: function () { alert(this.name); return this; } });
     var ClassB = $.fn.Class.create(ClassA, { initialize: function () { this.name = 'name:ClassB'; return this; } });
     var ClassC = $.fn.Class.create(ClassA, { showMe: function () { alert('ClassC'); return this.base.showMe(); } });
     var ClassD = $.fn.Class.create(ClassC, { showMe: function () { alert('ClassD'); return this.base.showMe(); } });
     var objA = new ClassA();
     var objB = new ClassB();
     var objC = new ClassC();
     var objD = new ClassD();
     objA.showMe().showName();   // 输出:“ClassA”、“name:ClassA”
     objB.showMe().showName();   // 输出:“ClassA”、“name:ClassB”
     objC.showMe().showName();   // 输出:“ClassC”“ClassA”、“name:ClassA”
     objD.showMe().showName();   // 输出:“ClassD”“ClassC”“ClassA”、“name:ClassA”
    

以下是完整代码(jQuery):


(function ($) {

    var Class = (function () {
        var IS_DONTENUM_BUGGY = (function () {
            for (var p in { toString: 1 }) {
                if (p === 'toString') return false;
            }
            return true;
        })();

        function subclass() { };

        function create() {
            /// <summary>
            /// 1: Class.create(context) - 创建一个新类
            /// 2: Class.create(parenClass, context) - 从父类继承并创建一个新类
            /// </summary>

            var parent = null, properties = $(arguments).toArray();
            if (isFunction(properties[0]))
                parent = properties.shift();

            function klass() {
                /// <summary>
                /// [类]请使用 new 新建一个当前类的对象
                /// </summary>
                /// <param name="plist" type="Object" optional="true">
                /// (可选)参数
                /// </param>

                // 构造对象时,先封装所有基类方法
                var self = this;
                this.base = { curtor: this.constructor };
                initBaseMethods(this.constructor);

                function initBaseMethods(baseclass) {
                    if (baseclass) {
                        var properties = keys(baseclass.prototype);
                        // 遍历封装当前类的基类方法
                        for (var property in baseclass.prototype) {
                            if (isFunction(baseclass.prototype[property])) addBaseMethod(property);
                        }
                    }
                }
                function addBaseMethod(property) {
                    // 生成一个同名的基类方法调用函数
                    self.base[property] = function () {
                        var curtor = self.base.curtor;
                        try {
                            if (curtor.baseclass) {
                                self.base.curtor = curtor.baseclass;
                                if (curtor.basemethods[property]) {
                                    // 如果有基类方法,直接调用基类方法
                                    return curtor.basemethods[property].apply(self, arguments);
                                } else {
                                    // 如果当前类没有同名基类方法,继续往下查找
                                    return self.base[property].apply(self, arguments);
                                }
                            } else {
                                // 如果没有基类,则返回当前类的同名方法
                                return curtor.prototype[property].apply(self, arguments);
                            }
                        } finally {
                            self.base.curtor = curtor;
                        }
                    };
                }
                // 基类方法封装完毕

                // 调用构造函数
                if (this.initialize) this.initialize.apply(this, arguments);
            }

            extend(klass, Class.Methods);
            klass.baseclass = parent;
            klass.basemethods = {};
            klass.subclasses = [];

            if (parent) {
                subclass.prototype = parent.prototype;
                klass.prototype = new subclass;
                parent.subclasses.push(klass);
            }

            for (var i = 0, length = properties.length; i < length; i++)
                klass.addMethods(properties[i]);

            if (!klass.prototype.initialize)
                klass.prototype.initialize = Prototype.emptyFunction;

            klass.prototype.constructor = klass;
            return klass;
        }


        function addMethods(source) {
            var ancestor = this.superclass && this.superclass.prototype,
            properties = keys(source);

            if (IS_DONTENUM_BUGGY) {
                if (source.toString != Object.prototype.toString)
                    properties.push("toString");
                if (source.valueOf != Object.prototype.valueOf)
                    properties.push("valueOf");
            }

            for (var i = 0, length = properties.length; i < length; i++) {
                var property = properties[i], value = source[property];
                if (isFunction(this.prototype[property])) {
                    // 发现父类存在同名方法时,将父类方法添加到当前类的基类方法列表
                    this.basemethods[property] = this.prototype[property];
                }
                this.prototype[property] = value;
            }

            return this;
        }

        return {
            create: create,
            Methods: {
                addMethods: addMethods
            }
        };

        function extend(destination, source) {
            for (var property in source)
                destination[property] = source[property];
            return destination;
        }
        function getArgumentNames(func) {
            var names = func.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
              .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
              .replace(/\s+/g, '').split(',');
            return names.length == 1 && !names[0] ? [] : names;
        }

        function isFunction(obj) {
            return Object.prototype.toString.call(obj) === "[object Function]";
        }

        function keys(object) {
            if (typeof (object) !== "object") { throw new TypeError(); }
            var results = [];
            for (var property in object) {
                if (object.hasOwnProperty(property)) {
                    results.push(property);
                }
            }
            return results;
        }

        function values(object) {
            var results = [];
            for (var property in object)
                results.push(object[property]);
            return results;
        }
    })();

    $.fn.extend({ Class: Class });

})(jQuery);

(注:主体部分不需要框架,可独立使用,把上面的代码去头去尾即可)

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载