Javascript 静态方法继承

Javascript static method inheritance

本文关键字:继承 静态方法 Javascript      更新时间:2023-09-26

我想创建一个Javascript类/对象,允许我有各种方法:

模型类

  • Model.all() » 静态方法
  • Model.find() » 静态方法
  • Model delete() » 实例方法
  • Model save() » 实例方法
  • Model.create() » 返回新模型实例的静态

对于静态方法,我可以使用以下命令定义它们:

Model.staticMethod(){ method }

而例如方法最好使用:

function Model(){
    this.instanceMethod = function(){}    
}

,然后创建一个新实例

还是使用原型?

var m = function Model(){
}
m.prototype.method() = function() {
}

现在假设我想创建一个基于 Model 的新类,如何不仅继承它的原型,还继承它的静态方法?

编辑:

为了避免混淆,这或多或少是我想创建的:

http://activejs.org/activerecord/index.html 和 http://activejs.org/activerecord/ActiveRecord/Model/index.html

我可以使用类似的东西定义一个新模型

var User = ActiveRecord.create({
    username: '',
    password: '',
    post_count: 0,
    profile: ''
}

然后创建实例

var jessica = User.create({
    username: "Jessica",
    password: "rabbit"
});

使用实例方法,例如

jessica.save();

还有类方法:

User.findByUsername('Jessica');
function Model() {}
// Methods in the instantiated object
Model.prototype = {
    constructor: Model,
    // Note that "delete" is a reserved word, so we need quotes
    'delete': function() {},
    save: function() {}
};
// Static methods
Model.all = function() {};
Model.find = function() {};
Model.create = function() {
    return new Model();
    // To be more generic, you can also:
    return new this();
};

使用 var InheritedModel = Object.create( Model ); 时,它还继承了静态方法。

var InheritedModel = Object.create( Model );
!!InheritedModel.all // true

但是,你不能做new InheritedModel(),因为它不是一个函数,使用Object.create( InheritedModel )不会给你实例方法。

如果要使用 new 实例化继承的类,则需要以下内容:

function InheritedModel() {}
InheritedModel.prototype = Object.create( Model.prototype );
// Copy all the static methods in the InheritedModel object
Object.keys( Model ).forEach( function( key ) {
    InheritedModel[ key ] = Model[ key ];
} );
编辑:看到您的

编辑后,这是我推荐您的解决方案:

function ActiveRecord( type, args ) {
    if ( type = 'users' ) {
        return new this.users();
    }
}
// Static method on ActiveRecord
ActiveRecord.create = function( type, args ) {
    return new ActiveRecord( type, args );
};
ActiveRecord.prototype = {
    constructor: ActiveRecord,
    // Instance method on ActiveRecord, you won't need it,
    // but your constructor does
    users: function( args ) {}
};
var Users = ActiveRecord.prototype.users;
Users.prototype = {
    constructor: Users,
    // Instance method on User's instance
    save: function() {}
}
// Static method on User
Users.create = function() {}

注释代码是伪代码。您可以通过以下方式实现相同的目标:

var modelInstanceMethods = {
    save: function() {
        /*
        insert into this.tableName blabla
        */
    },
    'delete': function() {
        /*
        delete from this.tableName blabla
        */
    }
};
var modelStatics = {
    create: function(obj) {
        return new this(obj);
    },
    all: function() {
        /*
        return select * from this.tableName.map( function( values ) {
            return new this(values);
        },this);
        */
    },
    find: function(id) {
        /*
        select * from this.tableName where id = id
        return new this(columnValues);
        */
    }

};
var ActiveRecord = {
    create: function( tableName, fields, methods ) {
        function Model( obj ) {
            this.tableName = tableName;
            this.fields = {};
            if( fields ) {
                for( var field in fields ) {
                    this.fields[field] = fields[field];
                }
            }
            if( obj ) {
                for( var field in obj ) {
                    this.fields[field] = obj[field];
                }       
            }
        }
        Model.tableName = tableName;
        Model.prototype = Object.create(modelInstanceMethods);
        Model.prototype.constructor = Model;
        for( var key in modelStatics ) {
            Model[key] = modelStatics[key];
        }
        if( methods ) {
            for( var key in methods ) {
                Model.prototype[key] = methods[key];
            }   
        }
        return Model;
    }
};

用法

var User = ActiveRecord.create('users',
    /* fields and their default values */
{
    id: 0,
    username: '',
    password: '',
    post_count: 0,
    profile: ''
}, {
    /*instance methods */
    setPassword: function(password) {
        this.fields.password = password;
    }
});
/*You can define static methods like this */
User.findByUsername = function(username) {
    /*select from this.tableName where userName = username
               return new this(columnValues) blabla
             */
};
var jessica = User.create( {
    username: "Jessica",
    password: "rabbit"
});
jessica.save();
User.findByUsername('Jessica');

你可以扩展对象的原型,向 Object.prototype 添加一个"extends"方法。这样,您将拥有一个看起来像java的继承方法。

(将"extends"属性定义为不可枚举很重要,否则会破坏jQuery)

Object.defineProperty(Object.prototype, "extends", {
        "enumerable": false,
        "value" : function(constructor) {
                /*Inheriting enumerable statick method and paramether
                from the super class */
                Object.keys( constructor ).forEach( function(key) {
                        this[key]= constructor[key];
                }.bind(this));
                /*Classic Javascript inheritance*/
                this.prototype= Object.create( constructor.prototype, {
                            "constructor": {
                                    "value": this,
                                    "configurable": true
                            }
                });             
                this.__super__= constructor;
        }
});

通过这样做可以轻松地将一个类继承到另一个类之后:

InheritedModel.extends(Model);
function InheritedModel(params){
       this.constructor.__super__.call(this, params);
       /* Or directly :
       Model.call(this,param);
       */
       /*Code specific to InheritedModel constructor */
}
/*To overload method from the super class:*/
InheritedModel.prototype.foo= function(params){
     var out= this.constructor.__super__.prototype.foo.call(this,params);
     /* Or
     var out= Model.prototype.foo.call(this,param);
     */
     /* code */
};
继承

模型将继承模型的所有实例方法和所有静态方法。

例:

function Model() {
        this.inheritedClassName= "Model";
};
Model.inheritedClassName= "Model";
Model.getClassName = function() {
       return this.name;
};
Model.prototype.getClassName = function() {
        return this.constructor.name;
};
InheritedModel.extends(Model);
function InheritedModel() {
        Model.call(this);
}
console.log(InheritedModel.inheritedClassName);/* Model */
console.log(InheritedModel.getClassName());/* InheritedModel */
var inheritedModel= new InheritedModel();
console.log(inheritedModel.inheritedClassName);/* Model */
console.log(inheritedModel.getClassName());/* InheritedModel */

我认为这是最好的解决方案。

怎么样,你有私有和公共方法:

function Model() {
    var privateMethods = {
       private1: function() {},
       private2: function() {},
       private3: function() {},
    };
    var publicMethods = {
    method1: function() {},
    method2: function() {
            //call a private method...
            privateMethods.private1();
        }
    };
    return publicMethods;
}

// Static methods
Model.all = function() {};
Model.find = function() {};
Model.create = function() {
    return new Model();
};