1

What would be the best (performance, memory wise) to achieve a clean way to create a class or some way to properly structure the code, that shares 2 variables (req, res) which have a decent object size.

And yes, for those who use Node.js it are the req and res variables, but it is irrelevant.

This is what I tried so far:

function Client(req, res){
  var self = this;

  self.req = req;
  self.res = res;

  route.call(self);
  handleRoute.call(self);
  handleRequestData.call(self);
}

function route(){
  var self = this;

  self.req.route = // ...
}

function handleAuth(){
  var self = this;

  self.req.auth = // ...
}

function handleRequestData(){
  var self = this;

  self.req.data = // ...
}

I am wondering if it could be improved, since I mentioned req and res are pretty decent objects with methods, properties. Since .call(self) you pass through the instance, would it be most effective way?

Also I don't like using "var self = this;" all the time, it is useless.

And btw, I don't want to use Coffeescript.

Solution 1. (fails because of the massive passing through req and res)

Lets assume we got to files 1. client.js

var Client = {
  route: function(req, res){},
  auth: function(req, res, callback){ callback(req, res); },
  getData: function(req, res, callback){ callback(req, res); } // async
}

file 2. main.js

var client = require('./client.js');

client.route(req, res); // fine because this is syncronous.

// This is where the problem is, massive passing through req and res parameters.
client.auth(req, res, function(req, res){
  client.getData(req, res, function(req, res){
    // Do something...
  });
});
onlineracoon
  • 2,822
  • 4
  • 44
  • 65

2 Answers2

1

I don’t know why you are constantly saving the context (this) in a local variable (self). You might as well use this all the way, unless you need to bring it into a local object with different scope.

Also, you can chain the other methods in the Prototype to gain access to the context inside them:

function Client(req, res){

  this.req = req;
  this.res = res;

  this.route();
  this.handleRoute();
  this.handleRequestData();
}

Client.prototype.route = function(){
  this.req.route = // ...
}

Client.prototype.handleAuth = function(){
  this.req.auth = // ...
}

Client.prototype.handleRequestData = function(){
  this.req.data = // ...
}

If you don’t want "public" methods, just do:

function Client(req, res){

  this.req = req;
  this.res = res;

  route.call(this);
  handleRoute.call(this);
  handleRequestData.call(this);
}

function route(){
  this.req.route = // ...
}

function handleAuth(){
  this.req.auth = // ...
}

function handleRequestData(){
  this.req.data = // ...
}
David Hellsing
  • 97,234
  • 40
  • 163
  • 203
  • private methods? the constructor does cascading, I don't want to be able to call client.handleAuth(); – onlineracoon Aug 21 '12 at 20:36
  • OK, you should probably mention that. BTW that doesn’t explain why you are putting `this` into `self`... – David Hellsing Aug 21 '12 at 20:37
  • Some functions are asyncronous, and redefine the "this" variable, but I still want to be able to refer to the actual instance of the class. – onlineracoon Aug 21 '12 at 20:39
  • Well that would be up to each function to deal with it’s context I guess. You could always pass it as an argument to save yourself some extra lines of code. – David Hellsing Aug 21 '12 at 20:50
1

Are you intending to reuse the route, handleAuth, and handleRequestData functions? They could be "private" to the Client constructor function:

function Client(req, res) {
    function route() {
        //...
    }

    function handleAuth() {
        //...
    }

    function handleRequestData() {
        //...
    }

    route();
    handleRoute();
    handleRequestData();
}

See that I didn't set req and res as this members. I don't know if this is mandatory in your case. Also, this is just the beginning of what could be done; as stated in the comments to this answer, every time a new Client is created, new instances of the private functions are created as well, wasting resources.

A more sophisticated approach could define Client using a self-invoking function expression:

var Client = (function() {
    function route(req, res) {
        //...
    }

    function handleAuth(req, res) {
        //...
    }

    function handleRequestData(req, res) {
        //...
    }

    // This is the constructor function:
    return function(req, res) {
        route(req, res);
        handleRoute(req, res);
        handleRequestData(req, res);
    }
})();

Here, Client is defined as the product of the function expression enclosed in the outermost parenthesis. The function expression returns the constructor function, which has access to the closure functions route, handleRoute, and handleRequestData. Note that each of these functions is defined with req and res parameters. This way, they behave like static private functions, and you can code and use them regardless of what's referenced by this.

About self = this: it's known that JavaScript may be very confusing about the this keyword. Some information here. So, sometimes it's convenient to assign this to a closure variable named like self or me. It should not be done blindly though... as anything after all.

Community
  • 1
  • 1
Humberto
  • 6,861
  • 2
  • 28
  • 45
  • 2
    I would not suggest this if you are planning on creating multiple Client objects. There will be multiple copies of the route, handleAuth, etc. functions, one for each instance. David's suggestion will deal better with this. – Scott Sauyet Aug 21 '12 at 20:42
  • You are right, @ScottSauyet. The code I posted may not be suitable for production. I'll expand my answer. – Humberto Aug 21 '12 at 20:44