3

我想创建一个允许我拥有各种方法的 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.htmlhttp://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');
4

4 回答 4

5
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(),因为它不是函数,并且 usingObject.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() {}
于 2012-06-19T09:08:10.393 回答
4

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

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');
于 2012-06-19T11:00:23.087 回答
1

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

(将“扩展”属性定义为不可枚举很重要,否则会破坏 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 */

};

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

例子:

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 */

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

于 2016-06-06T12:54:14.073 回答
-1

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

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();
};
于 2012-06-19T09:09:40.750 回答