0

I'm working with Javascript "classes", I have a parent "class" with a variable and a function, something like this

function WS() {
  this.auth = { client: '', password: '' };
  this.Execute = function(url, callback) {
    soap.createClient(url, function(err, client) {
      if (err) return callback(err);
      return callback(null, client);
    });
  }
}

The "subclass" uses this function and variable, like this

function Stats() {
  this.url = 'http://';

  this.emailsByDate = function(params, callback) {
    this.Execute(this.url, function(err, client) {
      if (err) return callback(err);
      client.Get(this.auth.concat(params), function(err, results) {
        if (err) return callback(err);
        return callback(results);
      });
    });
  }
}

Stats.prototype = new WS;

I'm getting through this.Execute() function, but this.auth variable is undefined, why is that

jtomasrl
  • 1,430
  • 3
  • 13
  • 22
  • Shouldn't it be: Stats.prototype = new WS(); ? – dudewad Aug 08 '14 at 17:44
  • You might replace the `Stats.prototype = new WS;` with [`util.inherits(Stats, WS);`](http://nodejs.org/docs/latest/api/util.html#util_util_inherits_constructor_superconstructor) and then adding your prototype functions after that line. – mscdex Aug 08 '14 at 17:46
  • See [How to access the correct `this` / context inside a callback?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback) and [Benefits of using `Object.create` for inheritance](http://stackoverflow.com/q/17392857/218196) – Felix Kling Aug 08 '14 at 17:59

1 Answers1

2

The context in which you are accessing this.auth isn't your Stats function, but instead your anonymous callback function.

You could either save the value of this.auth outside the callback function:

function Stats() {
  var auth = this.auth
  this.url = 'http://';

  this.emailsByDate = function(params, callback) {
    this.Execute(this.url, function(err, client) {
      if (err) return callback(err);
      client.Get(auth.concat(params), function(err, results) {
        if (err) return callback(err);
        return callback(results);
      });
    });
  }
}

Or you can bind the context of your callback function to that of your Stats function:

function Stats() {
  this.url = 'http://';

  this.emailsByDate = function(params, callback) {
    this.Execute(this.url, function(err, client) {
      if (err) return callback(err);
      client.Get(this.auth.concat(params), function(err, results) {
        if (err) return callback(err);
        return callback(results);
      });
    }.bind(this));
  }
}
Patrik Oldsberg
  • 1,540
  • 12
  • 14
  • 1
    In addition to having the correct binding of `this` you might consider calling `WS.call(this);` in your Stats constructor. – cjav_dev Aug 08 '14 at 17:51
  • @w1zeman1p That depends, it might be intended that the `auth` property is assigned to the prototype, as all the instances might want to share credentials. In that case `WS.call(this)` would make `auth` and `Execute` properties of each instance of `Stats`, and that might not be the desired effect. I think the real issue is that `Execute` and -- if intended -- `auth` should be moved to the prototype of `WS`, and the `Stats` prototype should inherit from the `WS` prototype using `Object.create`. Then the `WS.call(this)` call would make a lot of sense. – Patrik Oldsberg Aug 08 '14 at 18:12