Class methods in node.js

24,150

Solution 1

A couple of things are going on here, I've corrected your source code and added comments to explain along the way:

lib/User.js

// much more concise declaration
function User(db) {
    this.db = db;
}

// You need to assign a new function here
User.prototype.findOne = function (email, password, fn) {
    // some code here
}

// no need to overwrite `exports` ... since you're replacing `module.exports` itself
module.exports = User;

app.js

// don't forget `var`
// also don't call the require as a function, it's the class "declaration" you use to create new instances
var User = require('./lib/User');

// create a new instance of the user "class"
var user = new User(db);

// call findOne as an instance method
user.findOne(email, pw, callback);

Solution 2

You need to new User(db) at some point.

You could make an init method

exports.init = function(db){
  return new User(db)
}

And then from your code:

var User = require(...).init(db);
Share:
24,150
Patrick
Author by

Patrick

Location independent software nerd. I love breaking down complex situations into simple and minimalistic solutions. Available for new contracts anywhere in the world. #nodejs #javascript #devops #serverless

Updated on August 03, 2020

Comments

  • Patrick
    Patrick almost 4 years

    I've been trying for the last hour to write a user module for passport.js with the findOne, findOneOrCreate, etc. methods, but can't get it right.

    User.js

    var User = function(db) {
      this.db = db;
    }
    
    User.prototype.findOne(email, password, fn) {
      // some code here
    }
    
    module.exports = exports = User;
    

    app.js

    User = require('./lib/User')(db);
    User.findOne(email, pw, callback);
    

    I've been through dozens of errors, mostly

    TypeError: object is not a function
    

    or

    TypeError: Object function () {
      function User(db) {
        console.log(db);
      }
    } has no method 'findOne'
    

    How do I create a proper module with these functions without creating an object/instance of User?

    Update

    I went over the proposed solutions:

    var db;
    function User(db) {
      this.db = db;
    }
    User.prototype.init = function(db) {
      return new User(db);
    }
    User.prototype.findOne = function(profile, fn) {}
    module.exports = User;
    

    No luck.

    TypeError: Object function User(db) {
      this.db = db;
    } has no method 'init'
    
  • Robert K
    Robert K almost 12 years
    Yes, technically he's just imported the class reference... not instantiated it.
  • Patrick
    Patrick almost 12 years
    Hm, ok. I was hoping I'll get around an instance. This seems to be the nicest solution. Thanks!
  • 3on
    3on almost 12 years
    You are welcome. Java people call that a factory if I'm not mistaken.
  • Patrick
    Patrick almost 12 years
    Jepp, I went through all the patterns. It seems that some libraries do it without instance though. I updated the question, the solution doesn't quite work yet.
  • 3on
    3on almost 12 years
    Well you do not have to do "classes" that you new you can just have a modular approach if you do not need multiple instance of you that particular code. by having only exports.myFunction = function() {...}. Beside you did not get my first solution.
  • Patrick
    Patrick almost 12 years
    Ok, got it working now! I thought I still need the module.exports.
  • 3on
    3on almost 12 years
    You don't want to export the "class" you just want to exports the module method which returns you an Object User on which you have define some method in the its prototype.