2012-06-19 80 views
2

我想創建一個Javascript類/對象,讓我有不同的方法:的Javascript靜態方法繼承

Model類

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

現在,讓我們說,我想創建一個基於模型的一個新的類,如何繼承不僅是它的原型,而且它的靜態方法?

編輯:

,以避免混淆這或多或少是我想創造什麼:

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

是的,你應該使用'prototype',否則你爲每個實例化的對象創建新的函數對象。 – Esailija

+0

[在Javascript中使用'prototype'與'this'?](http://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript) –

+0

關於你的最後一個問題,你可能必須遍歷你添加到'Model'的方法,並將它們分配給新的類。 –

回答

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 ]; 
}); 

編輯:看到你的編輯後,這裏是解決方案,我會建議你:

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

是,代表團VS繼承 – silly

1

可以擴展對象的原型增加一個「擴展」的方法來Object.prototype中。 這樣你將有一個看起來像java的inherithance方法。

(定義是很重要的「擴展」屬性不枚舉否則會打破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 */ 

我覺得這是最好的解決辦法。