I'm using Node.js and am creating some models for my different objects.  This is a simplified version of what they look like at the moment.var Foo = module.exports = function () {    var values = { type: 'foo', prop1: '', prop2: '' };    function model() {}    model.init = function(val) {        _.extend(values, val);        return model;    }    model.store = function(cb) {        db.insert(values.type, values, cb);    }    model.prop1 = function(val) {        if(!arguments.length) return values.prop1;        values.prop1 = val;        return model;    }    return model;}Then I can do:var foo = Foo();foo.init({prop1: 'a', prop2: 'b'}).store(function(err) { ... }); I then create another model:var Bar = module.exports = function () {    var values = { type: 'foo', prop3: '', prop4: '' };    function model() {}    model.init = function(val) {        _.extend(values, val);        return model;    }    model.store = function(cb) {        db.insert(values.type, values, cb);    }    model.prop3 = function(val) {        if(!arguments.length) return values.prop3;        values.prop3 = val;        return model;    }    return model;}At which point I realize that a lot of the functions, like model.init and model.store will be reused in each of the models. But while they are exactly the same code, they depend on the local values contained in the model closure.  What's the best way to pull these functions out into a common base class that I can then use to extend all of my models with? 
How to refactor common methods that depend on local variables into a base class
javascript;node.js
Here are some tips:1) Turn Model into a constructor that accepts an object as the default values.Note: Constructors should start with a capital letter.Code:// Modelfunction Model(defaultValues) {    this.values = defaultValues || {};}Usage:var modelFoo = new Model({    type : 'foo',    prop1 : '',    prop2 : ''}); console.log( modelFoo.values.type === foo );  // true2) For readability, set the value of module.exports at the end of the file.Assuming Foo and Bar are in the same file you can export both of them like so.Code:module.exports = {    Foo : Foo,    Bar : Bar};3) Since Model is a constructor, you can access the interval values by using this and attach functions to it by using prototype.Also, returning this gives access to the current object instance.Old Code:model.init = function (val) {    _.extend(values, val);    return model;}model.store = function (cb) {    db.insert(values.type, values, cb);}New Code:Model.prototype.init = function (val) {    this.values = _.extend(this.values, val);    return this;};Model.prototype.store = function (cb) {    db.insert(this.values.type, this.values, cb);    return this;};4) Make sure that you define db in the module.Code:var db = require(db).db;5) Create a generic setter and getter function for the properties.Old Code:model.prop1 = function (val) {    if (!arguments.length)        return values.prop1;    values.prop1 = val;    return model;}New Code:Model.prototype.createPropSetterAndGetter = function (propName) {    this[propName] = (function () {        return function (val) {            if (!arguments.length) {                return this.values[propName];            }            this.values[propName] = val;        };    }());};Usage:var modelBar = new Model({    type : 'bar',    prop3 : '',    prop4 : ''});console.log( typeof modelBar.prop3 === undefined ); // truemodelBar.createPropSetterAndGetter(prop3);console.log( modelBar.prop3() ===  ); // truemodelBar.prop3( PAY ME! );console.log( modelBar.prop3() === PAY ME! ); //true and hurry.Final Result:var db = require(db).db;// Modelfunction Model(defaultValues) {    this.values = defaultValues || {};}Model.prototype.init = function (val) {    this.values = _.extend(this.values, val);    return this;};Model.prototype.store = function (cb) {    db.insert(this.values.type, this.values, cb);    return this;};Model.prototype.createPropSetterAndGetter = function (propName) {    this[propName] = (function () {        return function (val) {            if (!arguments.length) {                return this.values[propName];            }            this.values[propName] = val;        };    })();};// Foovar Foo = function () {    var modelFoo = new Model({            type : 'foo',            prop1 : '',            prop2 : ''        });    modelFoo.createPropSetterAndGetter(prop1);    return modelFoo;};// Barvar Bar = function () {    var modelBar = new Model({            type : 'bar',            prop3 : '',            prop4 : ''        });    modelBar.createPropSetterAndGetter(prop3);    return modelBar;};module.exports = {    Foo : Foo,    Bar : Bar};