2012-06-19 3 views
2

Я хочу, чтобы создать Javascript класс/объект, который позволит мне иметь различный метод: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() { 
} 

Теперь давайте предположим, что я хочу, чтобы создать новый класс, основанный на модели, как наследовать не только свои прототипы, но и его статические методы?

EDIT:

, чтобы избежать путаницы, это более или менее то, что я хочу создать:

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'); 
+0

Да, вы должны использовать 'prototype', иначе вы создадите новые объекты функций для каждого объекта, который вы создаете. – Esailija

+0

Возможный дубликат [Использование прототипа vs. «this» в Javascript?] (Http://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript) –

+0

Что касается вашего последнего вопрос, вам, вероятно, придется перебирать методы, добавленные в «Модель», и назначать их и новому классу. –

ответ

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'); 
+0

Мне очень нравится это осуществление, я Я изучаю его позже. большое спасибо! –

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(), потому что это не функция, а с помощью 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 ]; 
}); 

Edit: после просмотра правки, вот решение, которое я рекомендовал бы вам:

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() {} 
+0

Как наследовать статические методы с этим? –

+0

@MatteoPagliazzi с помощью 'Object.create' –

+0

@MatteoPagliazzi Отредактировано для добавления другого решения –

-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(); 
}; 
+0

Вы не можете использовать наследование с этим – Esailija

+0

да, делегация против наследования – silly

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

Я думаю, что это самое лучшее решение.

Смежные вопросы