这是我按照李站的甘露模型写的一个声明类的函数,可以声明类和继承,请各位高手看看我的和它的区别在哪里,谢谢    <script type="text/javascript">
    //类的继承
    function Class(){
        var defineClass = arguments[arguments.length-1];
        if(!defineClass) return;
        
        var baseClass = arguments.length > 1 ? arguments[0] : Object;
        if(!baseClass) return;
        
        _class.base = defineClass.create;
        if(!_class.base) return;
        function _class(){
            _class.base.apply(this, arguments);
        }
        
        _class.prototype = new baseClass();
        for(var member in defineClass)
            if(member!="create")
                _class.prototype[member] = defineClass[member];
        
        return _class;
    }
    
    var person = Class({
        create:function(name, age){
            this.name = name;
            this.age = age;
        },
        say:function(){
            alert(this.name+" is "+this.age+" years old");
        }
    });
    
    var worker = Class(person, {
        create:function(name, age, salary){
            person.base.apply(this, [name, age]);
            this.salary = salary;
        },
        show:function(){
            alert(this.name+"'s salary is "+this.salary+"$");
        }
    });
    
    var p = new person("soldierluo", 23);
    p.say();
    
    var w = new worker("luo", 33, 33333);
    w.say();
    w.show();
    </script>

解决方案 »

  1.   

    机制设计的不错,呵呵,仅看代码,有2个问题:
    1.  _class.prototype = new baseClass();
    创建了一个对象仅为了复制prototype,如果baseClass的构造函数需要参数或者逻辑较复杂,可能出错或者有副作用。例如我有一个类希望构造完就显示在页面上,那么每多继承一次,就会多一个这样的实例在页面。2. 子类没有对父类的引用,这样在子类中要调用基类同名方法会比较麻烦。不知道甘露模型有没这个问题,倒是没看过那个。
      

  2.   

    谢谢!1._class.prototype = new baseClass();的目的是让对象_class.prototype的隐式链指向baseClass.prototype,这里不是复制,所以不管baseClass的构造函数有无参数这里都是不用参数的,这里可能您有点不清楚2.这个问题还请详细指明,如能举个例子最好了,我也觉得有必要,但还没把这关系弄清楚
      

  3.   

    修改问题一后的,红色部分被替换成了其下的三句,解决了所说的副本的问题,汗!还是参考甘露模型出来的囧囧囧
        <script type="text/javascript">
        //类的继承
        function Class(){
            var defineClass = arguments[arguments.length-1];
            if(!defineClass) return;
            
            var baseClass = arguments.length > 1 ? arguments[0] : Object;
            if(!baseClass) return;
            
            _class.base = defineClass.create;
            if(!_class.base) return;
            function _class(){
                _class.base.apply(this, arguments);
            }
            
            //_class.prototype = new baseClass();
            function _prototype(){}
            _prototype.prototype = baseClass.prototype;
            _class.prototype = new _prototype();        for(var member in defineClass)
                if(member!="create")
                    _class.prototype[member] = defineClass[member];
            
            return _class;
        }
        
        var person = Class({
            create:function(name, age){
                this.name = name;
                this.age = age;
            },
            say:function(){
                alert(this.name+" is "+this.age+" years old");
            }
        });
        
        var worker = Class(person, {
            create:function(name, age, salary){
                person.base.apply(this, [name, age]);
                this.salary = salary;
            },
            show:function(){
                alert(this.name+"'s salary is "+this.salary+"$");
            }
        });
        
        var p = new person("soldierluo", 23);
        p.say();
        
        var w = new worker("luo", 33, 33333);
        w.say();
        w.show();
        </script>
      

  4.   

    嗯,第二个问题倒也不大:
    var worker = Class(person, {
            create:function(name, age, salary){
                person.base.apply(this, [name, age]);
                this.salary = salary;
            },
    }
    在这个子类调用了基类的create方法(类方法的override),如果子类有个属性个人觉得会好点:
    var worker = Class(person, {
            create:function(name, age, salary){
                this.baseClass.prototype.create.call(this,name,age);
                //person.base.apply(this, [name, age]);
                this.salary = salary;
            },
    }
      

  5.   


    参考甘露模型,修改后成了这样,可以通过this.base来调用基类的构造函数
        function Class(){
            var defineClass = arguments[arguments.length-1];
            if(!defineClass) return;
            
            var baseClass = arguments.length > 1 ? arguments[0] : Object;
            if(!baseClass) return;
            
            var _class = defineClass.create ? defineClass.create : function(){}    //声明的类既是构造函数,如果缺省的话使用默认构造函数
            
            function _prototype(){}
            _prototype.prototype = baseClass.prototype;
            var prototype = new _prototype();    //构造声明类的prototype
            
            for(var member in defineClass)  //将定义的类的元素复制到声明类的prototype上
                if(member!="create")
                    prototype[member] = defineClass[member];
            
            _class.prototype = prototype;
            _class.base = baseClass;
            
            return _class;
        }
        
        Object.prototype.base = function(){
            var Caller = Object.prototype.base.caller;
            Caller&&Caller.base&Caller.base.apply(this, arguments);
        }
        
        var person = Class({
            create:function(name, age){
                this.base();
                this.name = name;
                this.age = age;
            },
            say:function(){
                alert(this.name+" is "+this.age+" years old");
            }
        });
        
        var p = new person("soldierluo", 23);
        p.say();
        
        var worker = Class(person, {
            create:function(name, age, salary){
                this.base(name, age);
                this.salary = salary;
            },
            show:function(){
                alert(this.name+"'s salary is "+this.salary+"$");
            }
        });
        
        var w = new worker("luo", 33, 33333);
        w.say();
        w.show();
      

  6.   

    或许这样更适合,即当用户没有定义基类时,基本原本是Object,我觉得有点不妥,因为baseClass应该是类,及函数,虽然函数的本质也是Object,但我觉得用Function可能会更适合些,修改后如下
        function Class(){
            var defineClass = arguments[arguments.length-1];
            if(!defineClass) return;
            
            var baseClass = arguments.length > 1 ? arguments[0] : Function;
            if(!baseClass) return;
            
            var _class = defineClass.create ? defineClass.create : function(){}    //声明的类既是构造函数,如果缺省的话使用默认构造函数
            
            function _prototype(){}
            _prototype.prototype = baseClass.prototype;
            var prototype = new _prototype();    //构造声明类的prototype
            
            for(var member in defineClass)  //将定义的类的元素复制到声明类的prototype上
                if(member!="create")
                    prototype[member] = defineClass[member];
            
            _class.prototype = prototype;
            _class.base = baseClass;
            
            return _class;
        }
        
        Function.prototype.base = function(){
            var Caller = Function.prototype.base.caller;
            Caller&&Caller.base&Caller.base.apply(this, arguments);
        }
        
        var person = Class({
            create:function(name, age){
                this.base();
                this.name = name;
                this.age = age;
            },
            say:function(){
                alert(this.name+" is "+this.age+" years old");
            }
        });
        
        var p = new person("soldierluo", 23);
        p.say();
        
        var worker = Class(person, {
            create:function(name, age, salary){
                this.base(name, age);
                this.salary = salary;
            },
            show:function(){
                alert(this.name+"'s salary is "+this.salary+"$");
            }
        });
        
        var w = new worker("luo", 33, 33333);
        w.say();
        w.show();